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

Why aren't traits Sized by default?

提问人:kalkronline 提问时间:9/8/2023 最后编辑:kmdrekokalkronline 更新时间:9/9/2023 访问量:230

问:

我定义了一个特征,其中包含一个返回的函数,但会产生错误:ReadTagSelf

trait ReadTag {
    fn read_out(buf: &mut &[u8]) -> Option<Self>;
}
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

通过添加为超特征来修复错误,这是有道理的,但为什么默认值不像函数那样呢?SizedSized

fn my_sized<T>(t: T) { } // all good, Sized is opt-out :)

fn my_unsized<T: ?Sized>(t: T) { } // not allowed
Rust Traits 语言设计

评论

2赞 BallpointBen 9/8/2023
我猜答案是函数需要大小参数才能将其参数放在堆栈上,而特征则不存在这样的限制。
0赞 TheMaster 9/10/2023
这个问题在 meta 中讨论过

答:

9赞 kmdreko 9/8/2023 #1

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

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

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

trait Foo { }
trait Bar: Sized { }

struct Impl;
impl Foo for Impl { }
impl Bar for Impl { }

let x: &dyn Foo = &Impl;    // OK
// let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
                            // be made into an object

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


至于为什么其他所有东西(函数、结构、枚举、类型等)都是默认的,需要更多的猜测。在大多数其他上下文中,可能需要类型可能更为常见,并且到处都需要将是一个嘈杂的负担。后者(在需要未调整大小的类型时放宽约束)是两者中最不麻烦的。这个答案证实了这一点。SizedSizedT: SizedT: ?Sized