Consider this example:
fn callback<F>(f: F)
where
F: AsyncFn() + Send + 'static,
{
tokio::spawn(async move {
f().await;
});
}
#[tokio::main]
async fn main() {
callback(async || {});
}
The compiler reports an error
error: future cannot be sent between threads safely
--> src/main.rs:5:5
|
5 | / tokio::spawn(async move {
6 | | f().await;
7 | | });
| |______^ future created by async block is not `Send`
|
= help: within `{async block@src/main.rs:5:18: 5:28}`, the trait `Send` is not implemented for `<F as AsyncFnMut<()>>::CallRefFuture<'_>`
note: future is not `Send` as it awaits another future which is not `Send`
--> src/main.rs:6:9
|
6 | f().await;
| ^^^ await occurs here on type `<F as AsyncFnMut<()>>::CallRefFuture<'_>`, which is not `Send`
note: required by a bound in `tokio::spawn`
--> /playground/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.43.0/src/task/spawn.rs:168:21
|
166 | pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
| ----- required by a bound in this function
167 | where
168 | F: Future + Send + 'static,
| ^^^^ required by this bound in `spawn`
help: consider further restricting the associated type
|
3 | F: AsyncFn() + Send + 'static, <F as AsyncFnMut<()>>::CallRefFuture<'_>: Send
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
However, <F as AsyncFnMut<()>>::CallRefFuture<'_>: Send
is not writeable. So, how do we constrain the returned future of the async closure?