Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value does not live long enough with explicit lifetime, but does live long enough when omitted

Tags:

rust

lifetime

I have the following Rust program which passes a closure to a function generic in a lifetime 'a and a closure of type F, which calls the closure with a reference to some local data:

fn other_function<'a, F>(f: F)
    where F: Fn(&'a u32)
{
    let the_value = 0;
    f(&the_value);
}

fn main() {
    other_function(|_| { /* do nothing */ });
}

This fails to compile, with the following messages:

<anon>:5:8: 5:17 error: `the_value` does not live long enough
<anon>:5     f(&the_value);
                ^~~~~~~~~
<anon>:3:1: 6:2 note: reference must be valid for the lifetime 'a as defined on the block at 3:0...
<anon>:3 {
<anon>:4     let the_value = 0;
<anon>:5     f(&the_value);
<anon>:6 }
<anon>:4:23: 6:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 4:22
<anon>:4     let the_value = 0;
<anon>:5     f(&the_value);
<anon>:6 }
error: aborting due to previous error
playpen: application terminated with error code 101

My minimal example might be a bit too minimal now, since for this example a valid solution is to remove 'a, and 'a. However, I have a similar situation in a more complicated program in which explicit lifetimes seem required.

Is there a way of specifying lifetimes manually, such that the above program gets accepted by the compiler?

like image 835
Thierry Avatar asked Oct 12 '15 20:10

Thierry


1 Answers

The problem is that the caller of other_function gets to pick the lifetime that will fill in 'a, but you want other_function to do it. You could use a bit of syntax called higher ranked trait bounds:

fn other_function<F>(f: F)
    where F: for <'a> Fn(&'a u32)
{
    let the_value = 0;
    f(&the_value);
}

fn main() {
    other_function(|_| { /* do nothing */ });
}

As you pointed out, in this case, it makes more sense to omit the 'a completely. It's possible that your case needs something more complicated, but with your example nothing else makes sense. The caller cannot possibly specify any lifetime that will be compatible with a stack-allocated variable inside the method you are calling.

like image 159
Shepmaster Avatar answered Nov 15 '22 08:11

Shepmaster