This code:
trait Trait {}
fn dont_require_send(ts: Vec<Box<dyn Trait>>) {}
fn use_send(ts: Vec<Box<dyn Trait + Send>>) {
dont_require_send(ts)
}
fails with:
error[E0308]: mismatched types
--> src/main.rs:6:23
|
6 | dont_require_send(ts)
| ^^ expected trait `Trait`, found trait `Trait + std::marker::Send`
|
= note: expected type `std::vec::Vec<std::boxed::Box<Trait + 'static>>`
found type `std::vec::Vec<std::boxed::Box<Trait + std::marker::Send + 'static>>`
I kind of understand that Rust considers Trait
and Trait + Send
to be different types, and that is probably the reason for the error. On the other hand, I can't think of any reason why rejecting this particular code is actually useful. It is in fact quite annoying, it forces me to require Send
in the dont_require_send
function's parameters even though the function doesn't actually need it. Under some circumstances it could even make me implement several versions of dont_require_send
for different combinations of these marker traits.
Is there any workaround for this? Or are there any plans in the Rust compiler itself to make this code compile?
EDIT
What I've extracted from the comments: This question is a duplicate of Is there any way to convert Box> to Box>?. Both ways suggested there to work around the nuisance work for my question as well.
fn dont_require_send<U: Trait + ?Sized>(ts: Vec<Box<dyn U>>) {}
is probably the best solution if you have access todont_require_send
's sources. I personally don't like how the original intent is obscured, so I'm probably going to use this new idiom rarely.- If you don't have access to the original source, you can use the following to convert the objects at the call site:
ts.into_iter().map(|t| t as Box<Trait>).collect();
. Please note that just naively using the box-unbox trick from the other question doesn't work (why?):dont_require_send(ts.into_iter().map(|t| Box::new(*t)).collect())