需要 Sized 的 trait 与无法拥有该 trait 的 trait 对象有什么关系?

Hen*_*ing 9 traits rust

我有这个代码(操场):

trait NodeLike: Sized {}

fn main() {
    let s: Box<NodeLike> = panic!();
}
Run Code Online (Sandbox Code Playgroud)

哪个不编译:

trait NodeLike: Sized {}

fn main() {
    let s: Box<NodeLike> = panic!();
}
Run Code Online (Sandbox Code Playgroud)

毕竟我读过,我仍然不明白为什么它不能编译以及为什么它没有Sized约束。

据我所知:

  • Box<NodeLike>被视为Box<dyn NodeLike>对方法调用使用动态调度。
  • Box<NodeLike> 无论如何,无论其项目类型如何。
  • 有大小/无大小理论是必要的,因为有些类型的大小是事先未知的(如数组或字符串)。
  • 特征上的Sized标记强制实现类型的大小。

要求实现类型Sized与不能拥有该特征的对象(具有动态调度)有什么关系?

Dan*_*oni 5

Self: ?Sized特征类型本身是一个特质的对象,即对“对象安全”必需的属性,即使你可以有一个implSelf: ?Sized与性状Sized类型。因此混乱。

这是RFC 255 中决定的一个缺点,它处理对象安全(警告:过时的 Rust 语法)。

这是一篇很长的文章,但其中一种选择是通过仅分析 trait 的方法来确定“对象安全”。在 RFC 中承认,有这个限制会使一些本来可以工作的代码无法编译。(“这是一个突破性的变化,禁止一些今天合法的安全代码。”)。

如果我们仅将限制降低到实际需要它的 trait 成员函数,我们可以解决这个问题,例如编译:

trait NodeLike {
    fn method_foo(&self) -> Self
    where
        Self: Sized;
}

fn main() {
    let s: Box<NodeLike> = panic!();
    // Compiles!
}
Run Code Online (Sandbox Code Playgroud)

但是,我们不能通过Self: Sizedtrait 对象调用这些方法,这是一个在别处解释的限制。在这里,调用s.method_foo();会破坏编译。

请注意,Self: Sized即使该方法根本没有使用Self并且可能是可调用的特征对象方法,该约束也会限制编译。