Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I populate a vector of trait objects using an array?

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]`

Playground

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading