【问题标题】:Why are unsized types allowed in trait method declarations?为什么在 trait 方法声明中允许使用 unsized 类型?
【发布时间】:2021-02-16 22:05:00
【问题描述】:

为什么在 trait 方法声明中允许使用大小不一的类型?例如,这段代码编译:

trait Blah {
    fn blah(&self, input: [u8]) -> dyn Display;
}

但是实现Blah 是不可能的:

impl Blah for Foo {
    fn blah(&self, input: [u8]) -> dyn Display {
        "".to_string()
    }
} 
// error[E0277]: the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time
// error[E0277]: the size for values of type `[u8]` cannot be known at compilation time

blah一个默认实现也是不可能的:

trait Blah {
    fn blah(&self, input: dyn Display) -> dyn Display { "".to_string() }
}
// error[E0277]: the size for values of type `(dyn std::fmt::Display + 'static)` cannot be known at compilation time

也不允许嵌套大小不一的类型。这种不一致让我认为这是一个编译器错误:

trait Blah {
    fn blah(&self, input: [str]) -> dyn Display;
}
// error[E0277]: the size for values of type `str` cannot be known at compilation time

我发现一对old GitHub issues 声称这种行为是故意的,但我找不到原因。为什么这是故意行为?如果实现这种性质的 trait 是不可能的,为什么编译器不在 trait 声明中捕获它?

【问题讨论】:

    标签: rust


    【解决方案1】:

    我相信这里有两个不同的问题:未调整大小的函数参数和未调整的返回类型。

    无大小的参数类型

    feature(unsized_fn_params) 下的 nightly Rust 中实际实现并提供了未指定大小的函数参数。这很可能会在某个时候稳定下来,然后就有可能实现这样的特征:

    trait Crab {
        fn pinch(&self, data: str);
    }
    

    目前在稳定的 Rust 中无法实现。

    其实标准库uses这个特性要implement FnOnce() for Box<dyn FnOnce()>,这就需要将*self移到call_once方法中。由于FnOnce 是(某种)外部可见的¹,并且始终允许std 使用不稳定的功能,因此可能没有任何方法可以实现unsized_fn_params(每晚)而不允许特征函数拥有它们(稳定)。不过,这只是猜测。

    另见How to pass a boxed trait object by value in Rust?

    无大小的返回类型

    顾名思义,unsized_fn_params 只影响参数;即使在unsized_locals(更广泛、更宽松、更不完整的功能)下,仍然不允许未调整大小的返回值。因此,允许-> dyn Display 的论点远没有那么令人信服,而且有充分的理由证明这是一个实际的错误,或者至少值得一提。

    我相信这“故意”的部分,其实只适用于参数类型,包含返回类型是个意外。


    ¹ Fn trait 是特殊的,因为在 stable 中它们只能与 Fn(...) 语法一起使用,而不是 Fn<Args>,但在约束和 trait 对象中仍然有效。

    【讨论】:

      猜你喜欢
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-15
      • 1970-01-01
      相关资源
      最近更新 更多