rust

Why is this MyStruct<T> not coercing properly into MyStruct<dyn T>?


use std::marker::PhantomData;

trait SceneType {}

struct Scene<SceneType: ?Sized> {
    _phantom: PhantomData<SceneType>
}

pub enum SceneOne {}
impl SceneType for SceneOne {}

impl<SceneOne> Scene<SceneOne> {
    pub fn new() -> Self {
        Self {
            _phantom: Default::default()
        }
    }
}

fn main() {
    let scene = Scene::<SceneOne>::new();
    //works fine
    
    //1 let boxed_scene: Box<Scene<dyn SceneType>> = Box::new(Scene::<SceneOne>::new()); 
    // expected `Scene<dyn SceneType>`, found `Scene<SceneOne>` ... you could box the found value and coerce it to the trait object `Box<dyn SceneType>
    
    //2 let boxed_scene: Box<Scene<dyn SceneType>> = Box::new(scene) as Box<Scene<dyn SceneType>>; 
    // as` expression can only be used to convert between primitive types or to coerce to a specific trait object
}

Playground link

So the reason I ended up here is I wanted a new function to be generic over SceneType and have common functions that operate on any scene with

impl<T: SceneType> Scene<T> {
    ...

My problem is I can't box these types to store them in a vector because of the listed error messages. The error for 2 makes sense but I am trying to coerce it to a specific trait type as far as I am aware.


Solution

  • You are running afoul of the very limited Unsized Coercion rules.

    Coercion from sized to unsized, such as here from struct to trait, only work in a few limited cases, of interest here:

    So for example, if I define:

    struct Scene<ST: ?Sized>(ST);
    
    //  OR
    
    struct Scene<ST: ?Sized>(Box<ST>);
    

    Then the unsized coercion will work since all the points are ticked.

    On the other hand, with your definition:

    struct Scene<ST: ?Sized>(PhantomData<ST>);
    

    Then the unsized coercion from Scene<T> to Scene<U> is only possible if PhantomData<T>: Unsize<PhantomData<U>> (point 3), and that is not the case. You can see it's not listed in the implemented traits.