需要 Sized 的特征与无法拥有该特征的特征对象有什么关系?
What does a trait requiring Sized have to do with being unable to have trait objects of that trait?
我有这个代码 (playground):
trait NodeLike: Sized {}
fn main() {
let s: Box<NodeLike> = panic!();
}
哪个不编译:
error[E0038]: the trait `NodeLike` cannot be made into an object
--> src/main.rs:4:12
|
4 | let s: Box<NodeLike> = panic!();
| ^^^^^^^^^^^^^ the trait `NodeLike` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
看完之后,我仍然不明白为什么它不能编译,为什么它没有 Sized
约束。
据我所知:
Box<NodeLike>
被视为 Box<dyn NodeLike>
,它使用动态分派进行方法调用。
Box<NodeLike>
无论如何都是大小的,不管它的项目类型。
- sized/unsized 理论是必要的,因为有些类型的大小事先未知(例如数组或字符串)。
- 特征上的
Sized
标记强制执行类型的大小。
要求实现类型 Sized
与不能拥有该特征的对象(通过动态调度)有什么关系?
在 特征类型本身 上具有 Self: ?Sized
是特征对象所必需的 属性,即 'object safety',即使您可以在具有 Sized
类型的 Self: ?Sized
特征上具有 impl
。因此混乱。
这是在处理对象安全的 RFC 255 中确定的一个缺点(警告:过时的 Rust 语法)。
这是一篇很长的文章,但其中一种选择是通过仅分析特征的方法来确定 'object safety'。 RFC 中承认,具有此限制将使一些本可以运行的代码无法编译。 (“这是一项重大更改,禁止某些今天合法的安全代码。”)。
如果我们仅将限制降低到实际需要它的特征成员函数,例如这编译:
trait NodeLike {
fn method_foo(&self) -> Self
where
Self: Sized;
}
fn main() {
let s: Box<NodeLike> = panic!();
// Compiles!
}
但是,我们不能通过 trait 对象调用那些 Self: Sized
方法,这是一个限制,即 。在这里,调用 s.method_foo();
将中断编译。
请注意,Self: Sized
约束会限制编译,即使该方法根本不使用 Self
,否则可能是可调用的特征对象方法。
我有这个代码 (playground):
trait NodeLike: Sized {}
fn main() {
let s: Box<NodeLike> = panic!();
}
哪个不编译:
error[E0038]: the trait `NodeLike` cannot be made into an object
--> src/main.rs:4:12
|
4 | let s: Box<NodeLike> = panic!();
| ^^^^^^^^^^^^^ the trait `NodeLike` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
看完之后,我仍然不明白为什么它不能编译,为什么它没有 Sized
约束。
据我所知:
Box<NodeLike>
被视为Box<dyn NodeLike>
,它使用动态分派进行方法调用。Box<NodeLike>
无论如何都是大小的,不管它的项目类型。- sized/unsized 理论是必要的,因为有些类型的大小事先未知(例如数组或字符串)。
- 特征上的
Sized
标记强制执行类型的大小。
要求实现类型 Sized
与不能拥有该特征的对象(通过动态调度)有什么关系?
在 特征类型本身 上具有 Self: ?Sized
是特征对象所必需的 属性,即 'object safety',即使您可以在具有 Sized
类型的 Self: ?Sized
特征上具有 impl
。因此混乱。
这是在处理对象安全的 RFC 255 中确定的一个缺点(警告:过时的 Rust 语法)。
这是一篇很长的文章,但其中一种选择是通过仅分析特征的方法来确定 'object safety'。 RFC 中承认,具有此限制将使一些本可以运行的代码无法编译。 (“这是一项重大更改,禁止某些今天合法的安全代码。”)。
如果我们仅将限制降低到实际需要它的特征成员函数,例如这编译:
trait NodeLike {
fn method_foo(&self) -> Self
where
Self: Sized;
}
fn main() {
let s: Box<NodeLike> = panic!();
// Compiles!
}
但是,我们不能通过 trait 对象调用那些 Self: Sized
方法,这是一个限制,即 s.method_foo();
将中断编译。
请注意,Self: Sized
约束会限制编译,即使该方法根本不使用 Self
,否则可能是可调用的特征对象方法。