Send bites me, again!

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.

Maybe your on newer futures-preview. This commit changed boxed. Maybe post an issue if you can't track down why. (My glance does not see reason to have Send.)

1 Like

Oh, you're right, they just introduced a Send bound on boxed. Only discovered this morning that alpha15 came out, and was still looking at the docs for 14 but I suppose that Cargo was already using 15.

Ah well, I suppose I'm back to Box::pin( async move { ... } ) then.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.