If i have a function that returns a function:
fn<'r, T> ( p : T ) -> (&'r fn(&'r str) -> ~[(T,int)]) {
return |s| ~[(p, 0)]
}
However, This doesn't seem to work, I get the following (somewhat tautological) error:
playground.rs:10:8: 10:29 error: cannot infer an appropriate lifetime due to conflicting requirements
playground.rs:10 return |s| ~[(p, 0i)]
^~~~~~~~~~~~~~~~~~~~~
playground.rs:9:70: 11:5 note: first, the lifetime cannot outlive the block at 9:70...
playground.rs:9 pub fn result<'r, T>( p : T ) -> (&'r fn(&'r str) -> ~[(T, int)] ){
playground.rs:10 return |s| ~[(p, 0i)]
playground.rs:11 }
playground.rs:10:8: 10:29 note: ...due to the following expression
playground.rs:10 return |s| ~[(p, 0i)]
^~~~~~~~~~~~~~~~~~~~~
playground.rs:9:70: 11:5 note: but, the lifetime must be valid for the lifetime &'r as defined on the block at 9:70...
playground.rs:9 pub fn result<'r, T>( p : T ) -> (&'r fn(&'r str) -> ~[(T, int)] ){
playground.rs:10 return |s| ~[(p, 0i)]
playground.rs:11 }
playground.rs:10:8: 10:29 note: ...due to the following expression
playground.rs:10 return |s| ~[(p, 0i)]
^~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
I believe this is saying that the lifetime of the return of the function signature and the return value don't match up. However, I'm not sure how to annotate the lambda with a lifetime to make this work.
Lifetimes are what the Rust compiler uses to keep track of how long references are valid for. Checking references is one of the borrow checker's main responsibilities. Lifetimes help the borrow checker ensure that you never have invalid references.
Closures in Rust. Rust implements closures. A closure is like a lambda except it automatically captures anything it references from the enclosing environment. i.e. by default it can access any variable that is in the enclosing scope.
So this is a common mistake in rust, thinking that lifetime parameters actually affect lifetimes.
They do not, they only allow the compiler to know that a reference returned from a function lasts for a certain amount of time. This would be true anyway, but now the compiler knows it too and can allow more code to safe. This is a consequence of Rust only doing local analysis (looking at a single function at a time).
In this case, you are creating a stack closure. As the name suggests, a stack closure is created on the stack and you are then returning it up the stack. This is similar to this C code:
int *foo() { int a = 5; return &a; }
Clearly, the pointer (or "reference") to a
is invalid the moment you return. This is what Rust prevents.
In this case, the lifetime of the stack closure lasts for the duration of the function, but the lifetime parameter requires it to last longer than that (though there is nothing to say how long that is exactly), hence the mismatch error.
A basic rule-of-thumb is that if you have lifetime parameters on a function, you need each parameter in a position in the argument list and the return type, otherwise you are probably doing something wrong.
If you really wish to return a closure, then you must use a heap closure, ~fn (&str) -> ~[(T, int)]
, since that is allocated on the heap and can be passed around more freely (though still not copied).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With