The handler is indeed Send, but not Sync. In this code the reference to the handler is alive across the .await point which means the future returned by foo will store the reference. To make the future Send, the reference to the handler should also be Send, which requires the handler be Sync.
In case you are not familiar with it, an immutable reference to something is Send if that something is Sync. Your thing is not Sync, so the immutable reference is not Send.
Thanks! Indeed when I use handler F when calling bar, the original error is gone, then I encountered a similar error inside bar. (I was playing with F and &F back and forth.)
I snipped part of foo as it seems this forum does not allow a long program.
async fn foo<F, S> (handler: F)
<snip>
if (condition) {
let handler_clone = handler.clone();
bar(handler_clone).await;
}
}
<snip>
}
async fn bar<F, S>(handler: F)
where
F: Fn(Request<()>) -> S + Send + Clone + 'static,
S: Future<Output = Response<()>> + Send + 'static,
{
loop {
let req_handler = handler.clone();
executor.spawn({
let response = req_handler(req).await;
respond(response)
}).detach();
}
}
The error is reported when calling req_handler :
565 | let response = req_handler(req).await;
| ----------- ^
| |
| has type `&F` which is not `Send`
For some reason, rustc complains it's &F even when handler is F and reg_handler is a clone. I cannot understand why.
Regarding your last snippet, something is up. You're accessing some variable req in bar, which is not defined anywhere? And the error message you posted is incomplete. Can you post correct code with full error message please?
async fn foo<F,S> (handler: F, executor: &smol::Executor<'_>,)
where <snip>
{
loop {
<snip>
let handler_clone = handler.clone();
bar(handler_clone, executor).await;
}
<snip>
}
async fn bar<F,S> (handler: F, executor: &smol::Executor<'_>)
where <snip>
{
loop {
let (rx, tx) = channel::unbounded();
let req = create_request(rx, ...);
<snip>
let req_handler = handler.clone();
executor.spawn({
let response = req_handler(req).await;
respond(response)
}).detach();
}
}
The error is:
foo(handler, &my_executor)
});
| |_____________^ future returned by `foo` is not `Send`
564 | let response = req_handler(req).await;
| ^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `req_handler` maybe used later...
note: `req_handler` is later dropped here
|
564 | let response = req_handler(req).await;
| ----------- ^
| |
| has type `&F` which is not `Send`
help: consider moving this into a `let` binding to create a shorter lived borrow
|
564 | let response = req_handler(req).await;
| ^^^^^^^^^^^^^^^^
help: consider further restricting this bound
|
167 | F: Fn(Request<()>) -> S + Send + Clone + 'static + Sync,