为什么这个 MyStruct<T> 没有正确强制到 MyStruct<dyn T>?

问题描述 投票:0回答:1
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
}

游乐场链接

所以我最终来到这里的原因是我想要一个新函数在

SceneType
上通用,并且具有可在任何场景上运行的通用函数

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

我的问题是,由于列出的错误消息,我无法将这些类型装箱以将它们存储在向量中。 2 的错误是有道理的,但据我所知,我试图将其强制为特定的特征类型。

rust
1个回答
2
投票

您违反了非常有限的Unsized Coercion规则

从大小到未大小的强制转换,例如这里从结构到特征,仅在少数有限的情况下起作用,这里感兴趣:

  • 输入特征,因此
    SceneOne
    dyn SceneType
  • Foo<Type>
    Foo<Trait>
    如果:
    1. 类型实现了特征。
    2. 类型参数仅在 last 字段中出现 一次
      Foo
    3. Foo
      的最后一个字段本身可以被强制为适当的未调整大小。

例如,如果我定义:

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

//  OR

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

然后,由于所有点都已勾选,因此未调整大小的强制转换将起作用。

另一方面,按照你的定义:

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

那么,从

Scene<T>
Scene<U>
的无大小强制转换只有在
PhantomData<T>: Unsize<PhantomData<U>>
(第 3 点)的情况下才可能实现,但事实并非如此。您可以在已实现的特征中看到它没有列出

© www.soinside.com 2019 - 2024. All rights reserved.