-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can’t declare lifetime for closure that returns a reference #22340
Comments
Triage: there is still no way to declare lifetime parameters for closures like this today. |
Lets throw some ideas out there:
The last one is a little limited, but may actually be feasible unlike the others. |
I just ran into this issue today, trying to return a reference out of a closure that had the same lifetime as one of its arguments. Closures with lifetime, as well and type arguments would definitely be nice to have - if we had them, then I'm pretty sure closures would be just as powerful as functions. There's an RFC to implement them both: rust-lang/rfcs#1650 |
I played with a similar example today and found a funny workaround. |s| -> &str { &(s as &String)[..] } or even with |s| -> &str { &(s: &String)[..] } In this way, type inference can do it's job with a lifetime and the type of the argument is limited by the way of use in the body. |
There is another problem related to this one:
which essentiall prevents using closures for |
Lifetime inference does not work here, we need to define the lifetimes. But we can't do that with closures [1] so we use a function instead. [1]: rust-lang/rust#22340
Lifetime inference does not work here, we need to define the lifetimes. But we can't do that with closures [1] so we use a function instead. [1]: rust-lang/rust#22340
Lifetime inference does not work here, we need to define the lifetimes. But we can't do that with closures [1] so we use a function instead. [1]: rust-lang/rust#22340
An update: all of the examples given in the bug description do compile today, after being updated for Rust 1.0 syntax: fn print_first(list: Vec<String>) {
let x: &str = list
.first()
// .map(|s: &String| -> &str { &s[..] }) // OK
// .map(|s: &String| { &s[..] }) // OK
// .map(|s| -> &str { &s[..] }) // OK
.map(|s| { &s[..] }) // OK
.unwrap_or("");
println!("First element is {}", x);
}
fn main() {
print_first(vec![format!("hello"), format!("world")]);
} |
(However, what I do not yet know is whether the types we are actually inferring in all of the above cases are what the user expects. See related discussion on #56537...) |
I've been having a somewhat similar issue being unable to handle lifetimes with closures. Were explicit lifetimes ever added to closures?
#[cfg(test)]
mod tests {
#[test]
fn closure_lifetimes() {
let input: String = String::from("hello world");
let closure = |s: &str| -> &str {&s[..]};
let output: &str = closure(&input);
assert_eq!(input, output);
}
}
|
Isn't the compiler capable of detecting that the argument outlives the closure? fn main() {
let x = SimpleWrapper { value: 10 };
let foo = |wrapper: &SimpleWrapper| wrapper;
let y = foo(&x);
}
struct SimpleWrapper {
value: i32,
} |
Sometimes, I use a “cast function” to declare lifetimes: fn main() {
fn cast<T>(x: T) -> T
where T: for<'a> Fn(&'a SimpleWrapper) -> &'a SimpleWrapper
{
x
}
let x = SimpleWrapper { value: 10 };
let foo = cast(|wrapper: &SimpleWrapper| wrapper);
let y = foo(&x);
}
struct SimpleWrapper {
value: i32,
} |
When you declare closure argument types, there is no syntax to declare a lifetime parameter. And I guess lifetime elision does not apply to closures. Therefore, there seems to be no way to declare the type of a closure that returns a reference.
It compiles if you avoid declaring the type of the closure and depend on type inference. But then you would not be able to assign the closure to a local variable.
It gives a compiler error and a suggestion that does not make sense.
This bug is filed after I asked this question on stack overflow. It may be related to Region inference fails for closure parameter #17004.
The text was updated successfully, but these errors were encountered: