If I try to compile the following:
use async_trait::async_trait;
#[async_trait]
trait T: Sync {
async fn foo(&mut self) -> u32;
}
#[async_trait]
trait TInterface {
async fn foo(&mut self) -> u32;
}
#[async_trait]
impl<Q: T + Sync> TInterface for Q {
async fn foo(&mut self) -> u32 {
let x = <Q as T>::foo(self).await;
x
}
}
I get the error;
Compiling playground v0.1.0 (/home/prophet/playground)
error: future cannot be sent between threads safely
--> src/lib.rs:15:36
|
15 | async fn foo(&mut self) -> u32 {
| ____________________________________^
16 | | let x = <Q as T>::foo(self).await;
17 | | x
18 | | }
| |_____^ future created by async block is not `Send`
|
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
--> src/lib.rs:15:23
|
15 | async fn foo(&mut self) -> u32 {
| ^^^^ has type `&mut Q` which is not `Send`, because `Q` is not `Sync`
= note: required for the cast from `impl Future<Output = u32>` to the object type `dyn Future<Output = u32> + Send`
help: consider further restricting this bound
|
14 | impl<Q: T + Sync + std::marker::Send> TInterface for Q {
| +++++++++++++++++++
Two things stick out a strange:
-
The error complains Sync is missing, Q has a Sync bound, and in fact the trait T that also bounds Q also extends Sync. Q is definitely Sync, so this seems like a rustc bug? Unless somehow the magic async_trait is doing causes this?
-
The suggested code change is allegedly to fix Sync being missing, but if you look at the actual change it adds a Send bound.