Can't compile the use of `impl AsyncFn` within a spawned thread
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
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 AsyncFnMutseems 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 FnMutseems 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?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the two minimal examples in src/main.rs, starting with the spawned AsyncFn case and then the mutable async-closure case. Inspect the emitted Send and FnMut diagnostics and determine whether the behavior is an implementation bug or a language limitation. Done means documenting the confirmed behavior with a focused regression test or a precise diagnostic improvement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100