仅当将impl标记为“默认”时,关联的类型和类型参数之间才不匹配

时间:2018-06-25 11:40:17

标签: rust traits

以下代码会导致错误(Playground

#![feature(specialization)]

trait Foo {
    type Assoc;
    fn foo(&self) -> &Self::Assoc;
}

default impl<T> Foo for T {
    type Assoc = T;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

错误:

error[E0308]: mismatched types
  --> src/main.rs:20:9
   |
20 |         self
   |         ^^^^ expected associated type, found type parameter
   |
   = note: expected type `&<T as Foo>::Assoc`
              found type `&T`

这很奇怪,因为<T as Foo>::Assoc T,因此应该可以使用。甚至也陌生:当我从impl中删除default关键字时,它就可以工作(但是,当然,在我的实际代码中,我需要将impl标记为default)。

在特征定义(Playground)中提供默认值时,会发生相同的错误:

#![feature(specialization)]
#![feature(associated_type_defaults)]

trait Foo {
    type Assoc = Self;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

这是怎么回事?这是编译器错误吗?或者-这就是为什么我问这个问题-这个错误有意义吗,因为我还不了解专业化方面的一些特殊之处?万一这是个错误,mem::transmute肯定是安全的,可以吗?

1 个答案:

答案 0 :(得分:5)

Specialization功能没有显示稳定的迹象,主要是因为soundness concerns,所以您应该会遇到一些问题。

你有这个:

#![feature(specialization)]

trait Foo {
    type Assoc;
    fn foo(&self) -> &Self::Assoc;
}

default impl<T> Foo for T {
    type Assoc = T;
    fn foo(&self) -> &Self::Assoc {
        self
    }
}

但是,假设您添加了另一个具有自己关联类型的实现,但没有实现foo。此实现的foo将从另一个不太具体的实现“继承”:

impl<T: SomeConstraint> Foo for T {
    type Assoc = NotT;
}

那就有问题了。您的foo将返回一个T,但是,只要T为SomeConstraint,就会出现类型不匹配的情况,因为它应该返回一个NotT

RFC 2532 — associated type defaults在其Future Work section中提到了一种可能的解决方案。假设的default块可用于指示关联的类型和方法需要一起专门化。但是,没有迹象表明何时考虑使用此功能。