How to create a Box<dyn Trait> from a &dyn Trait

I'm pretty sure the answer can be found online, but I haven't found it yet.
I have tried:

let traitObject: &dyn Trait = /*...*/
Box::new(*traitObject)

but the compiler tells me that the size of "dyn Trait" can't be known at compile time.
Is there any other way to do this?

trait Trait {}
struct TraitObject {}
impl Trait for TraitObject {}

fn main() {
    let trait_object: Box<dyn Trait> = Box::new(TraitObject{});
    let trait_object_ref : &dyn Trait = trait_object.as_ref();
}

ok, thanks. But would like to turn a variable like trait_object_ref into a variable like trait_object, not the other way around, for example if I get it as function argument.

trait Trait {}
fn f(obj: &dyn Trait) -> Box<dyn Trait> {
/*... */
}

&dyn Trait doesn’t own the value behind the reference, so you need some way to get an owned value to place in the Box.

One way to handle that is just have a “clone_boxed” method in your trait
Playground

trait Trait {
    fn clone_boxed<'a>(&'a self) -> Box<dyn Trait + 'a>;
    
    fn act(&self);
}

impl Trait for String {
    fn clone_boxed<'a>(&'a self) -> Box<dyn Trait + 'a> {
        Box::new(self.clone())
    }
    
    fn act(&self) {
        println!("{self}");
    }
}

fn main() {
    let value = "Hello!".to_string();
    
    let obj: &dyn Trait = &value;
    
    obj.act();
    
    let boxed: Box<dyn Trait> = obj.clone_boxed();
    boxed.act();
}
3 Likes

Thanks a lot!

Box<dyn Trait> is usually short for Box<dyn Trait + 'static>, and it's not uncommon to want or need a Box<dyn Trait + 'static> instead of a lifetime-limited one like Box<dyn Trait + 'a>. For those, the clone_boxed pattern @semicoleon provided can be adjusted:

trait Trait {
    fn clone_boxed(&self) -> Box<dyn Trait /* + 'static */>;
    fn act(&self);
}

impl Trait for String {
    fn clone_boxed(&self) -> Box<dyn Trait /* + 'static */> {
        Box::new(self.clone())
    }

Note that the implementation did not change in the example, but now we have a Box<dyn Trait + 'static>. On the other hand, this won't work for non-'static types.

With this pattern, you can also

impl Clone for Box<dyn Trait> {
    fn clone(&self) -> Self {
        self.clone_boxed()
    }
}

Which pattern is better depends on your use case. If you can support Box<dyn Trait + 'a>, it might be the case that you can support &'a dyn Trait (aka &'a (dyn Trait + 'a)) instead.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.