Specify lifetime to life of function only?

Consider this rather contrived and useless infinitely recursive function:

pub fn f<'t, 'u, NumT>(l: &'t [NumT], n: &'u NumT) -> NumT
where
    &'u NumT: Add<&'t NumT, Output = NumT>,
{
    let x: NumT = n + &l[0];
    f(l, &x)
}

This is a cut down example of my actual code (which has a base case) but it very similar otherwise.

I feel something like this should compile, but the issue is the following:

   |
36 | pub fn f<'t, 'u, NumT>(l: &'t [NumT], n: &'u NumT) -> NumT
   |              -- lifetime `'u` defined here
...
41 |     f(l, &x)
   |     -----^^-
   |     |    |
   |     |    borrowed value does not live long enough
   |     argument requires that `x` is borrowed for `'u`
42 | }
   | - `x` dropped here while still borrowed

I think what is happening is that Rust is thinking that the lifetime 'u is asking for a lifetime that could last outside of f, where really f does not return a reference to n so it's lifetime never escapes it, so passing x to f should be valid.

How can I change the function definition to allow this? Note that I do want to add the two references from the slice l and the arg n without cloning them first (they could be BigInts in my case).

pub fn f<'t, NumT>(l: &'t [NumT], n: &NumT) -> NumT
where
    for<'u> &'u NumT: Add<&'t NumT, Output = NumT>,
{
    let x: NumT = n + &l[0];
    f(l, &x)
}

for<'u> ... is a higher rank lifetime bound (HRLB), this is closely related to higher rank type bounds (HRTB). This says, for any choice lifetime parameter 'u , this bound holds. Now we are not bound to any particular lifetime, so we can use any input lifetime we want.

Thank you (again) @RustyYato!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.