Using actual type for Box<dyn Any> fails to compile

Hi there,

I've define a struct that should be able to store Any actual type. However, when using an actual type the compiler complains with:

expected trait object `dyn Any`, found struct `Foo`

the fill code:

use std::any::Any;
use std::sync::Arc;
use std::sync::Mutex;

struct Foo {
    data: u32
}

struct Bar(Arc<Mutex<Box<dyn Any>>>);

fn main() {
    let foo = Arc::new(
        Mutex::new(
            Box::new(Foo { data: 32 })
        )
    );
    
    let bar = Bar(Arc::clone(&foo));
}

However, when instantiating the data that should contain Any data using a generic function the compiler is happy:

impl Bar {
    fn new<T: 'static>(val: T) -> Self {
        Self(Arc::new(Mutex::new(Box::new(val))))
    }
}

let bar = Bar::new(Foo { data: 64 });

I'm not able to figure why the behavior is different as in both cases the compiler is passing an actual type when creating the Box.

I'd appreciate if someone could shed a light on this :slight_smile:

You need an explicit cast:

fn main() {
    let foo = Arc::new(
        Mutex::new(
            Box::new(Foo { data: 32 }) as Box<dyn Any>
        )
    );
    
    let bar = Bar(Arc::clone(&foo));
}

This is because Box<dyn Any> is a different type from Box<Foo> -- there's an extra field for the vtable pointer. I'm not sure why a cast isn't needed in your second example.

This is a bit similar to Trait object question

In @cole-miller's version, you can do the coercion via just as _:

 Box::new(Foo { data: 32 }) as _

That's enough for it to compile.

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.