Rust:在默认方法实现中返回特征对象

Hen*_*ler 2 rust

当尝试从特征中的默认实现返回特征对象时,例如

trait Foo {
    fn foo(self: Box<Self>) -> Box<dyn Foo> {
        self
    }
}
Run Code Online (Sandbox Code Playgroud)

Rust 编译器抱怨说

error[E0277]: the size for values of type `Self` cannot be known at compilation time
note: required for the cast to the object type `dyn Foo`
Run Code Online (Sandbox Code Playgroud)

类型转换应该是 from Box<Self>to Box<dyn Foo>,为什么这需要调整 Self 的大小?

Cer*_*rus 5

将未调整大小的类型转换为特征对象是不可能的,因为这将迫使它同时具有两组元数据。

考虑这段代码:

trait Foo: 'static {
    fn foo(self: Box<Self>) -> Box<dyn Foo> {
        self
    }
}

trait Bar {}

impl Foo for dyn Bar {}

impl Foo for i32 {}

impl<T> Bar for T {}

fn main() {
    let boxed = Box::new(42);
    boxed.foo();

    let boxed: Box<dyn Bar> = Box::new(42);
    boxed.foo();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,没有什么可以禁止最后一次调用 - 所有签名都允许它。但是,如果我们强制Box<dyn Bar>,那么 goBox<dyn Foo>的虚拟函数表会在哪里dyn Bar?(当然,在这种情况下它是空的,但它仍然必须存在 - 空特征并不特殊)

但是,如果添加where Self: Sizedfoo,则最后一个调用将被正确拒绝:

error: the `foo` method cannot be invoked on a trait object
  --> src/main.rs:20:11
   |
2  |     fn foo(self: Box<Self>) -> Box<dyn Foo> where Self: Sized {
   |                                                         ----- this has a `Sized` requirement
...
20 |     boxed.foo();
   |           ^^^
Run Code Online (Sandbox Code Playgroud)