How to unbox an unsized type for storing in another struct?

I want to transfer a trait object from a Box into another container, like Arc.

use std::sync::Arc;

trait MyTrait {}
struct MyStruct {}
impl MyTrait for MyStruct {}

fn main() {
    // works as expected
    let dynamic: Arc<dyn MyTrait> = Arc::new(MyStruct{}) as Arc<dyn MyTrait>;

    // error
    let my_box: Box<dyn MyTrait> = Box::new(MyStruct{});
    let dynamic: Arc<dyn MyTrait> = Arc::new(*my_box) as Arc<dyn MyTrait>;
}

This give me:

error[E0277]: the size for values of type `dyn MyTrait` cannot be known at compilation time

Sounds pretty simple to me but I cannot figure out how to do this.

You can’t, try and keep unsized things in the smart pointer they will end up in. Once we get something like unsized-locals we can do this.

This has to do with the fact that Box has a different layout than Arc or Rc so you can’t just copy over the data.

1 Like

Ok, thanks.
In my case this would be Arc<RwLock<dyn MyTrait>> that I’d have to pass around, which is pretty unergonomic :frowning:
Is there an RFC I could follow?

Here’s the tracking issue for unsized rvlaues

2 Likes

You can create a wrapper type that works based off of closures callbacks if that makes it more bearable.

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

Thank you, but I think the longish type name adds less complexity in my case. It might help others, though.

1 Like

For moving a trait object from Box to Arc, are you maybe looking for Arc::from?

use std::sync::Arc;

trait MyTrait {}
struct MyStruct;
impl MyTrait for MyStruct {}

fn main() {
    let b: Box<dyn MyTrait> = Box::new(MyStruct);
    let a: Arc<dyn MyTrait> = Arc::from(b);
}
8 Likes

Yes, this would work for (some?) pointer-like types. Arc was an example. My actual type is Arc<RwLock<T>> and RwLock<T> doesn’t implement From<Box<T>>.

But thanks for pointing out that there are some types where this works.

Then you can’t, because the representaion of Arc<RwLock<T>> is too different from Box<T> to do a conversion.