0

I have a similar situation as Unable to tokio::run a boxed Future because the trait bound Send is not satisfied): I want to use tokio::run on types of Box<T: Future ...> where T does not implement Send.

My situation is different in that I didn't write the method which returns my Box, and so can't change its method signature. It performs a web request and returns this boxed future:

pub fn get_resource(&self,) -> Box<Future<Item = RestStruct, Error = Error<serde_json::Value>>>

Note the lack of Send.

Per the Tokio documentation, I need to implement Send on my boxed type, which isn't automatic even if the future's associated types are Send:

Astute readers may notice the explicit Send trait notation within the Box definition. The notation is added because Future is not explicitly Send by default; this causes problems later when trying to pass this future or one of its derivatives into tokio::run.

I'm having trouble figuring out an appropriately concise way to do this. It seems like something along these lines should work:

impl<T, I, E> Send for T
where
    T: Future<Item = I, Error = E>,
    I: Send,
    E: Send,
{
}

I get a number of surprising errors. I'll detail them below, but my question can be generally phrased, how do I specify: any type satisfying a given first trait under certain trait bounds must also implicitly satisfy a second trait?


The errors my solution produced:

the trait std::marker::Send requires an unsafe impl declaration

I think I understand that one based on the documentation about Send, though to clarify: this would indeed constitute a "properly implemented Send" as described there, because the associated types are Send?

type parameter T must be used as the type parameter for some local type (e.g., MyStruct<T>)

I understand this to be related to the newtype workaround as described in the docs, which would really get in the way of doing what I want to do if so. Does this mean I can't accomplish what I want? Is there something like a type alias for bounded traits that would get around this?

conflicting implementations of trait std::marker::Send for type &_

That one, I don't understand at all. &_ is far broader a type than the constrained one I tried to specify using all those where bounds; I would not expect &_ to be Future<Item = I: Send, Error = E: Send>.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
qqq
  • 1,360
  • 1
  • 9
  • 24
  • 1
    *I didn't write the method which returns my `Box`* — then you are basically out of luck. Your question is essentially the same as saying "I have a type that doesn't implement `Display`; how do I lie to the compiler and make it believe the type does?". You don't have any guarantees that the returned type *can* be sent between threads, which very well might mean that it **cannot**. – Shepmaster Apr 14 '19 at 21:17
  • 1
    Additionally, your hypothetical blanket implementation cannot work and for good reason. Just I could easily have `struct IsNotSend(...); impl Future for IsNotSend { Item = i32, Error = () }`. Both `Item` and `Error` are `Send`, but the struct itself is not. – Shepmaster Apr 14 '19 at 21:20
  • I see, that helps me understand where i was making a false conclusion, because even if `Item` and `Error` are `Send` types, there's no reason non-send elements could not also exist in the containing concrete type. In my case, the returned implementer of `Future` coincidentally has no other data contents, but this can't be known based on the signatures. Thank you. – qqq Apr 14 '19 at 21:50

0 Answers0