async fn test(v:&i32)->&i32{ // #1
v
}
fn main(){
let f = |v:&i32| async move{ // #2
v
};
}
#2 can result in a compile error that says:
|
7 | let f = |v:&i32| async move{
| ________________-___-_^
| | | |
| | | return type of closure `{async block@src/main.rs:7:22: 9:6}` contains a lifetime `'2`
| | let's call the lifetime of this reference `'1`
8 | | v
9 | | };
| |_____^ returning this value requires that `'1` must outlive `'2`
However, Shouldn't #2 be similar to #1? It appears to me that #2 can be de-sugared to
// It doesn't infer it as generic/HR really, it infers
// it as returning one specific lifetime, but anyway
async fn test<'a>(v:&i32) -> &'a i32 { // #1
v
}
Which is the same problem as the snippet below. I.e. the compiler is extremely bad at higher-ranked closure inference.
// error: lifetime may not live long enough
let lambda = |v: &i32| v;
I wonder whether this workaround does the same things as the following
fn funnel<F>(f: F) -> F
where
F: for<'a> Fn(&'a i32) -> Pin<Box<dyn Future<Output = &'a i32> + 'a>>
{
f
}
This is such that the input lifetime is associated with the output. Moreover, if we had a closure binder, then the compile error could be resolved as simple as:
#![feature(closure_lifetime_binder)]
fn main(){
let lambda = for<'a> |v: &'a i32|->&'a i32 { v };
}
The crucial issue here is that the compiler cannot associate the input lifetime with the output for the closure expression, right?
For the non-async version or the Pin<Box<dyn>> versions, yes. For the unboxed future, we'd need -> impl Trait in closure declarations or such in addition (as the futures are not nameable).
Yes, or at least it does not without something like the funnel workaround -- in combination with the fact that lifetime elision in closure declarations doesn't work the same as lifetime elision in function signatures, Fn bounds, etc.
Many cases work when you have enough control to steer the compiler, so it is capable in more ways than can be easily expressed. But the language has yet to give programmers enough control in a complete or ergonomic manner.
(And probably it will become more capable with time, too.)