I'm working on a little observable pattern which generates a futures 0.3 stream of events for observers, however the compiler insists that the observable object be Send, which I don't want, and more I don't manage to understand why... The code is here.
I make a default impl to reduce boilerplate for the user, and I will use self in a boxed future like so:
fn notify( &mut self, evt: Event ) -> ReturnNoSend< Result<(), Error> >
{
async move
{
for (name, ref mut tx) in self.observers()
{
let mut e = evt.clone();
e.set_name( name.clone() );
// TODO: this is a problem. If one channel fails, the others won't be tried anymore.
//
await!( tx.send( e ) )?;
}
Ok(())
}.boxed()
}
where the return type is:
pub type ReturnNoSend<'a, R> = Pin<Box< dyn Future<Output = R> + 'a >> ;
The error I get is:
error[E0277]: `T` cannot be sent between threads safely
--> src/observable_impl.rs:37:5
|
37 | }.boxed()
| ^^^^^ `T` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `T`
= help: consider adding a `where T: std::marker::Send` bound
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut T`
= note: required because it appears within the type `[static generator@src/observable_impl.rs:24:3: 37:4 self:&mut T, evt:Event _]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src/observable_impl.rs:24:3: 37:4 self:&mut T, evt:Event _]>`
= note: required because it appears within the type `impl core::future::future::Future`
So what I don't get:
- In my own code, I don't require Send, except for on the Event type, which would be good to be send so observers can be in another thread.
- looking at the code for std::future::Future there are no Send bounds anywhere
- same for generator
- the boxed method that is marked in the error comes from futures-preview. It does not require Send
So none of the types involved requires Send, then why does rustc. I intend for this future to be spawned in a Localpool executor. It would be completely fine if the compiler refused to compile code that tries to spawn it on a Threadpool.