Open
Description
I'm getting the following errors when attempting to use a closure within a spawned thread, the errors are a bit too cryptic for me to understand how to correct the following code.
#[tokio::main]
async fn main() {
tokio::spawn(async move {
let text = String::from("");
something(&text).await;
});
}
async fn something(text: &String) {
let try_something = async || {
println!("{text}");
};
// try_something().await; // works
retry(try_something).await; // fails
}
async fn retry(action: impl AsyncFn()) {
action().await;
}
Error:
error: implementation of `Send` is not general enough
--> src/main.rs:3:5
|
3 | / tokio::spawn(async move {
4 | | let text = String::from("");
5 | | something(&text).await;
6 | | });
| |______^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 &String`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 &String`, for some specific lifetime `'1`
Using impl Fn() -> impl Future
instead of impl AsyncFn
then works but for my use case, a mutable closure is needed which blocks me from using impl FnMut
because of the following issue:
#[tokio::main]
async fn main() {
let mut count = 0;
let try_something = async || {
count = 1;
};
retry(try_something).await;
}
async fn retry<F>(mut action: impl FnMut() -> F) // fails but would work if this was instead `impl AsyncFnMut()`
where
F: Future<Output = ()>,
{
action().await;
}
Error:
error: async closure does not implement `FnMut` because it captures state from its environment
--> src/main.rs:26:25
|
26 | let try_something = async || {
| ^^^^^^^^
...
30 | retry(try_something).await;
| ----- required by a bound introduced by this call
|
note: required by a bound in `retry`
--> src/main.rs:33:36
|
33 | async fn retry<F>(mut action: impl FnMut() -> F)
| ^^^^^^^^^^^^ required by this bound in `retry`
Essentially,
- I need to use a mutable reference in a closure which means I'd want to use
async || {}
instead of|| async {}
, - but using
impl AsyncFnMut
seems to break as soon as it's within a spawned thread which means I'd want to instead try:impl FnMut -> impl Future
, - but using
impl FnMut
seems to break the use ofasync || {}
which means I'd want to instead try:|| async {}
, - but using
|| async {}
no longer allows me to use a mutable reference which then breaks the required functionality - and so I then repeat back to step 1, and I've been stuck on that loop for the last couple of hours, each time trying a different variation to try and get it to work but with no luck.
- Is
impl AsyncFn*
not allowed within spawned threads? - Can
async || {}
not be passed to a function that takesimpl FnMut -> impl Future
?