1

I have the following code:

pub trait Handler<T: Clone>: Clone {
    fn invoke(&self) -> Result<(), std::io::Error>;
}

#[derive(Clone)]
pub struct App<T: Clone> {
    handlers: Vec<Box<dyn Handler<T>>>,
}

fn main() -> Result<(), std::io::Error> {
    #[derive(Clone)]
    struct MyHandler<T: Clone> { tt: T }

    impl<T: Clone> Handler<T> for MyHandler<T> {
        fn invoke(&self) -> Result<(), std::io::Error> { () }
    }

    let app = App { handlers: vec![ MyHandler{ tt: 0 }, MyHandler{ tt: 5 } ] };

That generates a compile error:

error[E0038]: the trait `Handler` cannot be made into an object
 --> src/main.rs:8:5
  |
8 |     handlers: Vec<Box<dyn Handler<T>>>,
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Handler` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

Even if I'm not trying to convert the trait into a concrete object. I don't understand: the box struct should allow me to store an unknown sized type.

The aim is to store a Vec of Handler implementors in order to have invoke method for all object.

Boiethios
  • 38,438
  • 19
  • 134
  • 183
allevo
  • 844
  • 1
  • 9
  • 20
  • Hi there! I think your question is answered by ["How to clone a struct storing a boxed trait object?"](https://stackoverflow.com/a/30353928/2408867). In short: if you have `Clone` as supertrait, your trait becomes non object-safe, meaning it cannot be made into an object. Please let us know if the linked answer sufficiently answers your question! – Lukas Kalbertodt Aug 28 '19 at 10:33
  • 1
    The error message is really not optimal, though. It should point to the `Clone` supertrait bound. But you probably want to read a bit about "object safety". For example [here](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects) or [here](https://stackoverflow.com/a/44097369/2408867). – Lukas Kalbertodt Aug 28 '19 at 10:36
  • So, it's not possible to implement Clone trait for a struct with `Vec>` where MyTrait implements Clone? – allevo Aug 28 '19 at 14:33
  • It is possible, as the linked answer shows. It's just not possible to call `clone()` on a trait object (due to object safety). Therefore you have to build your own `clone` method that returns a boxed trait object. – Lukas Kalbertodt Aug 28 '19 at 16:14

0 Answers0