“必须指定关联类型...”,但不使用

时间:2019-12-06 23:51:34

标签: rust associated-types dynamic-dispatch trait-objects

为什么即使从未使用过关联类型,这里也需要它?

trait Tr {
    type Ty;
    fn go(&self) -> () {}
}

fn foo(t: dyn Tr) -> () {
    t.go()
}

我明白了

2 |   type Ty;   
  |   -------- `Ty` defined here   
...  
6 | fn foo(t: dyn Tr) -> () {  
  |           ^^^^^^ associated type `Ty` must be specified

1 个答案:

答案 0 :(得分:1)

您正在制作特征对象,并且特征对象的要求是指定所有关联的类型。您的情况非常简单,并且特征的方法不使用关联的类型,但是object safety rules是为更一般的情况设计的。

如果您只是使用受Tr约束的类型参数,则无需指定关联的类型:

fn foo<T: Tr>(t: T) -> () {
    t.go()
}

这是因为可以为调用T的每个foo推断关联的类型。

如果特征对象被允许具有未指定的关联类型,则函数内的代码将无法推断出它。在这种情况下,您可能会争辩说,这仅应限制该函数的作用,但是为特征对象类型的定义给出了对象安全规则,无论其实际使用方式如何。这使得考虑起来更简单,因为在某些情况下不会使用trait对象,而在其他情况下则无法使用。


顺便说一句,即使您在函数签名中为对象指定了关联的类型,也必须通过引用或框将其传递给对象,例如:

fn foo(t: &dyn Tr<Ty = SomeType>) -> () {
    t.go()
}

这是因为trait对象的大小在编译时未知。取而代之的是,您需要将它们放在参考之后,该参考 的大小已知。