I feel like this code should work since Box<Dog>
s are supposed to be able to be implicitly converted into Box<dyn Animal>
s in most situations:
struct Dog {}
trait Animal {}
impl Animal for Dog {}
fn main() {
let _: Vec<Box<dyn Animal>> = [Dog {}, Dog {}]
.into_iter()
.map(Box::new)
.collect();
}
However, I get the following compiler error:
error[E0277]: a value of type `Vec<Box<dyn Animal>>` cannot be built from an iterator over elements of type `Box<Dog>`
--> src/main.rs:9:10
|
9 | .collect();
| ^^^^^^^ value of type `Vec<Box<dyn Animal>>` cannot be built from `std::iter::Iterator<Item=Box<Dog>>`
|
= help: the trait `FromIterator<Box<Dog>>` is not implemented for `Vec<Box<dyn Animal>>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`
For more information about this error, try `rustc --explain E0277`.
I also tried inserting a .map(Into::into)
to convert the Box<Dog>
s into Box<dyn Animal>
s, but that gives the error the trait bound `Box<dyn Animal>: From<Box<Dog>>` is not satisfied
.
So how am I supposed to collect my Box<Dog>
s into Box<dyn Animal>
s?
You're almost there. The problem is that Box::new()
takes T
and gives Box<T>
. No coercion is possible.
Instead, you should provide a closure |v| Box::new(v)
, but even that is not enough, because the compiler doesn't immediately realize it needs to coerce, and when it does it's too late (you can read more here). You need to hint it. A simple as
will suffice: |v| Box::new(v) as _
.