Hey, I am trying to write an async method that takes a closure as an argument and applies it to self. Included a minimal example:
use futures::future::{self, BoxFuture};
use futures::Future;
#[derive(std::fmt::Debug, Clone)]
struct MyStruct {
x: u32,
}
impl MyStruct {
fn check<'a, F, T, FR>(&'a mut self, f: F) -> BoxFuture<'a, T>
where
F: (FnOnce(&mut Self) -> FR) + Send + 'a,
FR: Future<Output = T> + Send,
T: Send,
{
Box::pin(async move { f(self).await })
}
fn func(&mut self) -> BoxFuture<'_, ()> {
Box::pin(future::ready(()))
}
}
fn main() {
let mut my_struct = MyStruct { x: 0 };
let _inner_fut = my_struct.check(|my_struct| async move {
my_struct.func().await;
});
}
I am using a single dependency, futures = "0.3.7"
$ rustc --version
rustc 1.47.0 (18bf6b4f0 2020-10-07)
This is the compilation error I get:
$ cargo run
Compiling check_borrow2 v0.1.0 (/home/real/temp/check_borrow2)
error: lifetime may not live long enough
--> src/main.rs:26:50
|
26 | let _inner_fut = my_struct.check(|my_struct| async move {
| _______________________________________----------_^
| | | |
| | | return type of closure is impl futures::Future
| | has type `&'1 mut MyStruct`
27 | | my_struct.func().await;
28 | | });
| |_____^ returning this value requires that `'1` must outlive `'2`
error: aborting due to previous error
error: could not compile `check_borrow2`.
My guess is that the compiler thinks the return value form the closure somehow outlives the my_struct reference, but I have to admit I don't fully understand the compiler's error here. Who is lifetime '2?
As a further clarification, I am using BoxFuture and not impl Future here, because in the original code the method is inside a trait, and using impl Future tricks there is not possible yet.
I tried to play with the lifetimes, but couldn't figure it out. I also noticed that if the call to func() is omitted, the code seems to compile. Any help is appreciated!