3

Is it possible to collect a Vec<&dyn Trait> from an iterator of values implementing Trait?

Here is an example, based on the Vector of objects belonging to a trait question:

trait Animal {
    fn make_sound(&self) -> String;
}

struct Dog;
impl Animal for Dog {
    fn make_sound(&self) -> String {
        "woof".to_string()
    }
}

fn main() {
    let dogs = [Dog, Dog];
    let v: Vec<&dyn Animal> = dogs.iter().collect();

    for animal in v.iter() {
        println!("{}", animal.make_sound());
    }
}

this fails with error[E0277]: a value of type "Vec<&dyn Animal>" cannot be built from an iterator over elements of type &Dog`

however, if you use push the dogs individually into the vec (like in the answer to the original question) it works without issues.

let dog1: Dog = Dog;
let dog2: Dog = Dog;

let v: Vec<&dyn Animal> = Vec::new();
v.push(&dog1);
v.push(&dog2);
Florian sp1rit
  • 575
  • 1
  • 7
  • 20

1 Answers1

7

In order to collect an Iterator of a struct into a Vector of a trait that gets implemented by the Struct, it is possible to use the map method of the iterator to cast the borrowed struct into a borrowed trait.

let dogs = [Dog, Dog];
let v: Vec<&dyn Animal> = dogs.iter().map(|a| a as &dyn Animal ).collect();

See this playground for more info.

Florian sp1rit
  • 575
  • 1
  • 7
  • 20
  • 2
    And since you specify the trait in the type of `v` you can also do `.map(|a| a as _)` and let the compiler do its magic. – rodrigo Aug 26 '21 at 11:57