The solution from How do I store a variable of type `impl Trait` in a struct? suggests creating a Future
trait object. Doing that in my real code generates an error that the type is not Send
, but the only difference between the working and non working version is the presence or absence of the cast to dyn Future
.
Why does the compiler see these as different and how do I resolve the problem?
Here's a simplified version of the problem:
use std::future::Future;
fn uses_impl_trait() -> impl Future<Output = i32> {
async { 42 }
}
fn uses_trait_object() -> Box<dyn Future<Output = i32>> {
Box::new(async { 42 })
}
fn requires_send<T: Send>(_: T) {}
fn example() {
requires_send(uses_impl_trait()); // Works
requires_send(uses_trait_object()); // Fails
}
error[E0277]: `dyn std::future::Future<Output = i32>` cannot be sent between threads safely
--> src/lib.rs:15:19
|
11 | fn requires_send<T: Send>(_: T) {}
| ------------- ---- required by this bound in `requires_send`
...
15 | requires_send(uses_trait_object());
| ^^^^^^^^^^^^^^^^^^^ `dyn std::future::Future<Output = i32>` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = i32>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn std::future::Future<Output = i32>>`
= note: required because it appears within the type `std::boxed::Box<dyn std::future::Future<Output = i32>>`
From Sending trait objects between threads in Rust, I already know that I can change the trait object to Box<dyn Future<Output = i32> + Send>
, but why does this difference exist?