TraitObject incompatible with Clone?

Is it possible to create Box of Clone-able trait object?

trait Engine : Clone {
    fn do_it(&self);
}

fn bar(_engine: &Box<dyn Engine>) {

}
5 | fn bar(_engine: &Box<dyn Engine>) {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Engine` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

Clone is Sized: pub trait Clone : Sized and this makes trait object-unsafe. I've read RFC-255 https://rust-lang.github.io/rfcs/0255-object-safety.html but I can not say I understood argumentation why trait's bound Self: Sized would break object safety. I've also read proposed mitigations from this RFC, but can not see how to use them in my case.

What I really want is something like this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7a200bdfa8ebdb5a133870e7d5fcab2d
Is there any way to achieve it?

Would something like this work? You can fiddle with BoxClone as much as you need to to make this work for you,

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fbb194571236d34a300a33c3c3d6fd7b

But if you have a finite number of engines, you should consider using an enum instead. Trait objects are really akward to use if you need to clone them. Another option is to use Arc<..> or Rc<..> instead of Box, that way you can always clone them.

2 Likes

A good article for explaining Object Safety is @huon's Object Safety.

While not ideal, this crate also makes cloning trait objects possible: https://docs.rs/objekt/0.1.2/objekt/

1 Like

Yes, I thought about it and in the end I simply parameterized functions with generics.
In this particular case it is ok, but generally speaking I am concerned with code multiplication during monomorpisation in cases when there are a lot of functions to be parameterized and a lot of traits implementations.

But at least I found better explanation: Clone returns Self, which means that caller must know size at compile time. Now that's make sense. I'll read @Michael-F-Bryan link to understand better Sized issue.