As far as I know, in function f, there can never be a impl Sync object transferred between threads. f can only accesses impl Sync through references, and &impl Sync is, by definition, Send. So what’s the problem?
I also noticed that if I split off the await part, the function compiles successfully:
use futures::lock::Mutex;
fn f(value: &(Mutex<()>, impl Sync)) -> impl Send + '_ {
async move {
let m = Mutex::lock(&value.0);
m.await;
}
}
This is currently a limitation in the type checking of async blocks. What you’re doing is not wrong, for some reason rustc currently considers the type of *value [which is a place-expression that kind-of apprears as a “temporary” in the desugaring of &value.0 into &(*value).0 however, place-expressions like this one don’t have to actually produce temporaries, and in this case I’m suspecting that this is the kind of detail that the current heuristic doesn’t consider] to be part of the types of values that are held over the .await point. This hopefully gets fixed eventually, in the meantime it’s possible to work around it, e.g. like you did yourself.
I strongly suspect there is one, but I have never checked. I just remember having seen similar problems in this forum before, so it’s definitely nothing entirely unknown. Maybe you can find it yourself or someone else knows some issue(s).