kal*_*ine 2 language-design traits rust
我定义了一个特征ReadTag,其中包含一个返回的函数Self,但这样会产生错误:
trait ReadTag {
fn read_out(buf: &mut &[u8]) -> Option<Self>;
}
Run Code Online (Sandbox Code Playgroud)
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> src/lib.rs:2:37
|
2 | fn read_out(buf: &mut &[u8]) -> Option<Self>;
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
Run Code Online (Sandbox Code Playgroud)
Sized通过添加为超级特征来修复错误,这是有道理的,但为什么Sized不像函数那样默认呢?
fn my_sized<T>(t: T) { } // all good, Sized is opt-out :)
fn my_unsized<T: ?Sized>(t: T) { } // not allowed
Run Code Online (Sandbox Code Playgroud)
文档介绍Sized了为什么它不是特征的默认/隐式绑定:
\n\n特征没有隐式
\nSized绑定,因为这与特征对象不兼容,根据定义,特征需要与所有可能的实现者一起工作,因此可以是任何大小。虽然 Rust 会让你绑定
\nSized到一个特征,但你稍后将无法使用它来形成一个特征对象:Run Code Online (Sandbox Code Playgroud)\ntrait Foo { }\ntrait Bar: Sized { }\n\nstruct Impl;\nimpl Foo for Impl { }\nimpl Bar for Impl { }\n\nlet x: &dyn Foo = &Impl; // OK\n// let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot\n // be made into an object\n
默认情况下禁止dyn Trait听起来确实是一个糟糕的选择。
至于为什么其他所有东西(函数、结构、枚举、类型等)Sized 都是默认的,需要更多的猜测。Sized可能在大多数其他情况下需要类型更为常见,并且T: Sized在任何地方都需要类型将是一个嘈杂的负担。后者(当需要T: ?Sized未确定大小的类型时放松约束)是两者中最不麻烦的。得到这个答案的证实。