为什么特征默认没有调整大小?

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)

kmd*_*eko 9

文档介绍Sized了为什么它不是特征的默认/隐式绑定:

\n
\n

特征没有隐式Sized绑定,因为这与特征对象不兼容,根据定义,特征需要与所有可能的实现者一起工作,因此可以是任何大小。

\n

虽然 Rust 会让你绑定Sized到一个特征,但你稍后将无法使用它来形成一个特征对象:

\n
trait 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
Run Code Online (Sandbox Code Playgroud)\n
\n

默认情况下禁止dyn Trait听起来确实是一个糟糕的选择。

\n
\n

至于为什么其他所有东西(函数、结构、枚举、类型等)Sized 都是默认的,需要更多的猜测。Sized可能在大多数其他情况下需要类型更为常见,并且T: Sized在任何地方都需要类型将是一个嘈杂的负担。后者(当需要T: ?Sized未确定大小的类型时放松约束)是两者中最不麻烦的。得到这个答案的证实。

\n