Hello,
I'm trying to write a function taking a FnOnce
async
closure which is then executed in its body.
This closure should be called with a reference and should be able to use captured references, but I am not able to support both at the same time.
Sadly my knowledge of Rust lifetimes is not particularly great, but I think it should be possible to express this construct.
I would appreciate any help!
Here is my progress so far:
use ::core::future::Future;
use ::futures::future::{BoxFuture, FutureExt};
#[derive(Debug)]
struct Token();
async fn test<F, Fut>(f: F) // Attempt 1
where
F: FnOnce(Token) -> Fut,
Fut: Future<Output = ()>,
{
let token = Token();
f(token).await;
}
async fn test_ref<F>(f: F) // Attempt 2
where
for<'a> F: FnOnce(&'a Token) -> BoxFuture<()> + 'a,
{
let token = Token();
f(&token).await;
}
async fn main() {
let mut string = String::from("My string");
// works, but argument to closure is not a reference
let reference = &mut string;
test(|token: Token| async move {
reference.push('b');
println!("{:?}", token);
})
.await;
// works, but outer value is not taken by reference
test_ref(|token: &Token| async move {
string.push('b');
println!("{:?}", token);
}.boxed())
.await;
// does not work
let mut string = String::from("My string");
let reference = &mut string;
test_ref(|token: &Token| async move {
reference.push('b');
println!("{:?}", token);
}.boxed())
.await;
}
Error message:
Compiling playground v0.0.1 (/playground)
error[E0597]: `string` does not live long enough
--> src/lib.rs:43:21
|
43 | let reference = &mut string;
| ^^^^^^^^^^^ borrowed value does not live long enough
44 | test_ref(|token: &Token| async move {
| ______________________________-
45 | | reference.push('b');
46 | | println!("{:?}", token);
47 | | }.boxed())
| |_____________- returning this value requires that `string` is borrowed for `'static`
48 | .await;
49 | }
| - `string` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error