I don't understand why this cannot compile. Everything seems good.
fn main(){
let len = 10;
|string: &str| -> &str {&string[0..len]};
}
The output is here.
error: lifetime may not live long enough
--> src/main.rs:3:29
|
3 | |string: &str| -> &str {&string[0..len]};
| - - ^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
| | let's call the lifetime of this reference `'2`
| let's call the lifetime of this reference `'1`
How can I let the compiler knows lifetime '1 is equivalent to '2? Thanks.
Probably not enough type annotations for inference to kick in, and/or borrowing len is problematic (it is borrowed because it doesn't need to be moved, as usize: Copy).
Providing an explicit type for the whole function and creating a move closure solves the problem.
I think it was the type annotation impl FnMut(&str) -> &str took the effect.
This code still cannot compile.
In practice, this closure is not alone in one function. I'm afraid I cannot use type annotation.
With inference not working, you need to explicitly annotate the lifetimes. But this is not possible for closures in stable Rust. In nightly with an unstable feature you can have:
#![feature(closure_lifetime_binder)]
fn main(){
let len = 10;
for<'a> |string: &'a str| -> &'a str {&string[0..len]};
}
The way to write the correct lifetime dependency in the closure’s type signature on stable rust is by passing it through some helper function with an appropriate Fn* trait bound.
fn main() {
let len = 10;
fn with_desired_signature<F: Fn(&str) -> &str>(f: F) -> F {
f
}
with_desired_signature(|string| &string[0..len]);
}
Why don't you explicitly annotate the type using a separate function as I suggested? That doesn't require nightly.
I don't understand why it is a problem that the closure is not "alone". Just wrap it in a function like I provided in the playground, call that function, assign its return value to a variable, and you'll be able to use that variable as if it were assigned the closure directly.
Yes, it is. Well, actually when you first proposed your workaround, I was aware that type annotation cannot be avoided. These two workaround both revolve around type annotation, the difference is just a form, isn't it?