Beginner Question: Is it possible to transform a `& trait` into `Box<>`?

Hi evryone,
after having great feelings of success with learning Rust I'm currently got stucked into the following problem:
Given an API which takes a trait object by reference (&dyn ...), is it possible to put this reference into a collection with boxed trait objects (Box<dyn ...> )? The following example fails if uncommented with the described compiler message because it's not possible to deref unsized trait references. If I understood it right it's easy to convert a box into a & by calling box.as_ref() so how to do it vice versa?

pub trait Node {}

pub struct ExampleNode {
}

impl Node for ExampleNode {
}

pub struct Container {
    children: Vec<Box<dyn Node>>,
}

impl Container {
    pub fn add_node(&mut self, t: &dyn Node) {
        // let b: Box<dyn Node> = Box::new(*t); // ^^^^^^^^ doesn't have a size
        // self.children.push(b);               // known at compile-time
    }
}

fn main() {
    let mut container = Container{children: Vec::new()};
    container.add_node(&ExampleNode{});
}

No, you can never coerce &(shared reference) to box. Say if you got &Vec<u8> as &dyn Write, and coerce it to Box<dyn Write>, than the underlying heap memory will be double-freed.

Usually, Box<dyn Trait> is constructed from Box<ActualType>, so you should first make the box with Box::new(ExampleNode{}) as Box<dyn Node>.

1 Like

That's only half of it. The other half of it is that you can't move data out of a borrow.

Box<T> owns data. &T doesn't. You can never turn &T into Box<T> unless you somehow clone the data that it points to. If that's what you want, see the objekt crate:

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.