我定义了一个特征ReadTag,它包含一个返回Self的函数,但这样会产生一个错误:

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

通过添加Sized作为超级特征修复了这个错误,这是有意义的,但为什么Sized不像函数一样是默认的呢?

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

fn my_unsized<T: ?Sized>(t: T) { } // not allowed

推荐答案

关于Sized的文档介绍了为什么它不是特征的默认/隐式界限:

特征没有隐式的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听起来确实是一个糟糕的 Select .


至于为什么Sized is在其他所有东西(函数、 struct 、枚举、类型等)上都是默认的,需要更多的猜测.在大多数其他环境中,更常见的情况可能是需要Sized个类型,而到处都需要T: Sized个类型将是一种繁重的负担.后者(当需要未调整大小的类型are时,放宽T: ?Sized的限制)是两个中最不麻烦的.this answer人证实了这一点.

Rust相关问答推荐

移植带有可变borrow 的C代码-卸载期间错误(nappgui示例)

为什么父作用域中的变量超出了子作用域

在Rust中,在实现特征`Display`时,如何获取调用方指定的格式?

在自定义序列化程序中复制serde(With)的行为

在本例中,为什么我不能一次多次borrow 可变变量?

无符号整数的Rust带符号差

我们能确定Rust会优化掉Clone()吗?如果它会立即掉落?

如何实现Deref;多次;?

找不到 .has_func 或 .get_func 的 def

Rust,如何从 Rc> 复制内部值并返回它?

需要一个有序向量来进行 struct 初始化

在描述棋盘时如何最好地使用特征与枚举

为什么数组不像向量那样在 for 块之后移动?

Rust 将特性传递给依赖项

在 Rust 中为泛型 struct 编写一次特征绑定

从 Cranelift 发出 ASM

相交着色器从 SSBO 中读取零

需要括号的宏调用中的不必要的括号警告 - 这是编写宏的糟糕方法吗?

在 Rust 中有条件地导入?

为什么可以从不可变 struct 的字段中移动?