So I asked this question at "async-trait" issue tracker but it looks like this is something related to not just the library.
I'm invoking an async method that in itself calls another async method of a struct (async-trait constrained method). It says 'future' is not Sync, and I tried with every possible "dyn Trait + Send + Sync", "unsafe impl Send/Sync" bandage wherever possible to no avail. The driver method is given as a box-pinned async function.
Could somebody give me a clue as to where this issue is coming from?
type Driver = Box<dyn Fn() -> Pin<Box<dyn Future<Output = Response<Body>> + Send + Sync + 'static>>
+ Send
+ Sync
+ 'static>;
// driver
let handler: Driver = Box::new(|| {
Box::pin(async {
outer.outer_func().await
})
});
handler();
// Traits and structs defined somewhere else
[async_trait::async_trait]
pub trait AsyncTrait {
fn async_func(&self);
}
pub trait AsyncTraitObj;
[async_trait::async_trait]
impl AsyncTrait for AsyncTraitObj {
fn async_func(&self) {}
}
struct Outer {
trait_object: Arc<dyn AsyncTrait + Send + Sync>,
}
impl Outer {
pub fn outer_func(&self) {
self.trait_object.async_func().await; // warning (cause of error): future is not 'Sync' as this value is used across an await
}
}
EDIT
I came up with a reproducible example with smaller footprint.
pub struct S {}
#[async_trait::async_trait]
pub trait Tr: Send + Sync {
async fn a(&self)
where
Self: Send + Sync + 'static;
}
#[async_trait::async_trait]
impl Tr for S {
async fn a(&self)
where
Self: Send + Sync + 'static,
{
}
}
unsafe impl Send for S {}
unsafe impl Sync for S {}
Struct A;
impl A {
pub fn f() {
let f: Box<
dyn Fn() -> Pin<Box<dyn Future<Output = ()> + Send + Sync + 'static>>
+ Send
+ Sync
+ 'static,
> = Box::new(move || {
let s: Arc<dyn Tr> = Arc::new(S {});
Box::pin(async move { // future cannot be shared between threads safely
let s = s.clone();
s.a().await; // future is not 'Sync' as it awats another future which is not 'Sync'
})
});
}
}