I'm running into an issue when trying to write a wrapper around an async function. I've tried a few different versions of the code, but whether I specify the wrapped function as returning boxed future or I specify it as an async function, the result is pretty much the same. Here's a playground. The code is as follows:
use std::future::Future;
use std::pin::Pin;
struct Foo<'a> {
foo: &'a str,
}
async fn wrap<'a, F>(mut foo: Foo<'_>, f: F)
where
F: FnOnce(&mut Foo<'_>) -> Pin<Box<dyn Future<Output = ()> + 'a>>,
{
f(&mut foo).await;
}
fn bar(_foo: &mut Foo<'_>) {
}
fn wrapped<'a>(foo: &'a mut Foo<'_>) -> Pin<Box<dyn Future<Output = ()> + 'a>> {
Box::pin(async move {
println!("foo: {}", foo.foo);
})
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let s = String::from("foo");
let foo = Foo {
foo: &s
};
wrap(foo, wrapped).await;
}
If I change the ellided lifetimes of a Foo
struct to the wrapper's function lifetime, I don't get the error, but instead s does not live long enough
playground. What's curious is that it says that the lifetime introduced by the Pin<Box<dyn Future<....> + 'a>>>
is static, not sure why's that the case.
I guess my question is the following: is there any way to make code like this work? Ie. allow to pass a lifetime bound struct to an async function passed as an argument?