Why is the following code an error? There is a blanket implementation for [T; N] into Vec<T>, so why does dyn Foo not match Fooable in this context? Is there a workaround which does not involve cloning the Fooable?
trait Foo {}
struct Fooable {}
impl Foo for Fooable {}
pub fn main() {
let bar: Vec<Box<dyn Foo>> = [
Box::new(Fooable {}),
].into();
}
Error:
error[E0277]: the trait bound `Vec<Box<dyn Foo>>: From<[Box<Fooable>; 1]>` is not satisfied
--> src/main.rs:10:7
|
10 | ].into();
| ^^^^ the trait `From<[Box<Fooable>; 1]>` is not implemented for `Vec<Box<dyn Foo>>`
|
= help: the following other types implement trait `From<T>`:
<Vec<T, A> as From<Box<[T], A>>>
<Vec<T, A> as From<VecDeque<T, A>>>
<Vec<T> as From<&[T]>>
<Vec<T> as From<&mut [T]>>
<Vec<T> as From<BinaryHeap<T>>>
<Vec<T> as From<Cow<'a, [T]>>>
<Vec<T> as From<[T; N]>>
<Vec<u8> as From<&str>>
and 2 others
= note: required because of the requirements on the impl of `Into<Vec<Box<dyn Foo>>>` for `[Box<Fooable>; 1]`
>Solution :
You can fix the error by manually casting the box like this:
trait Foo {}
struct Fooable {}
impl Foo for Fooable {}
pub fn main() {
let bar: Vec<Box<dyn Foo>> = [
// Turn a Box<Fooable> into a Box<dyn Foo>
Box::new(Fooable {}) as Box<dyn Foo>,
].into();
}
Remember that by default, Rust builds replaces trait method calls directly with calls to the implementation if it exists. A object’s "type" only exists at compile time, at run time there are no types. dyn types are different. They store some extra data that allows finding the actual variant of the method to call at runtime.
For this reason, a Box<dyn Foo> is actually a completely different type than a Box<Fooable>. Converting from one to another requires modifying the data to include information about finding the correct method pointers. Thus the conversion is not not free and requires a explicit step.