Challenge 12

Spot the Bug

Identify why the code fails to compile and suggest a way to fix it.

trait Animal {
    fn make_sound(&self);
}

struct Dog {
    name: String,
}

impl Animal for Dog {
    fn make_sound(&self) {
        println!("{} says: Woof!", self.name);
    }
}

struct Cat {
    name: String,
}

impl Animal for Cat {
    fn make_sound(&self) {
        println!("{} says: Meow!", self.name);
    }
}

fn main() {
    let dog = Dog {
        name: String::from("Rex"),
    };
    let cat = Cat {
        name: String::from("Lisa"),
    };

    let animals: Vec<dyn Animal> = vec![dog, cat];

    for animal in animals {
        animal.make_sound();
    }
}

Solution

Click to Show/Hide Solution

The Bug:

The bug in the code is due to the attempt to create a vector of trait objects (dyn Animal) directly from instances of concrete types (Dog and Cat).

This is not possible because trait objects have a dynamic size that is not known at compile time.

To fix the bug, you need to box the instances of Dog and Cat before adding them to the vector.

Solution:

#![allow(unused)]
fn main() {
  let animals: Vec<Box<dyn Animal>> = vec![Box::new(dog),Box::new(cat)];
}

In the corrected code, dog and cat are boxed (Box::new(dog) and Box::new(cat)) before being added to the vector. This allows them to be treated as trait objects with a known size at compile time.