我有这个代码(操场):
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与不能拥有该特征的对象(具有动态调度)有什么关系?
其Self: ?Sized对特征类型本身是一个特质的对象,即对“对象安全”必需的属性,即使你可以有一个impl在Self: ?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并且可能是可调用的特征对象方法,该约束也会限制编译。