如何将特征与使用特征相关类型作为参数的超级特征绑定?

时间:2016-03-04 15:23:39

标签: rust

我有一个特征Trait,其关联类型为Trait::Associated。我试图通过要求它可以通过其关联类型进行索引来约束该特征,如下所示:

use std::ops::Index;

pub trait Trait: Index<Trait::Associated> {
    type Associated;
}

但是,编译器会抱怨相关类型不明确

  
error[E0223]: ambiguous associated type
 --> src/main.rs:3:24
  |
3 | pub trait Trait: Index<Trait::Associated> {
  |                        ^^^^^^^^^^^^^^^^^ ambiguous associated type
  |
  = note: specify the type using the syntax `<Type as Trait>::Associated`

我也尝试将关联类型称为Self::Associated,但编译器会对类型和特征之间的循环引用提出抗议:

  
error[E0391]: cyclic dependency detected
 --> src/main.rs:3:1
  |
3 | pub trait Trait: Index<Self::Associated> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic reference
  |
note: the cycle begins when computing the supertraits of `Trait`...
 --> src/main.rs:3:1
  |
3 | pub trait Trait: Index<Self::Associated> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: ...which then again requires computing the supertraits of `Trait`, completing the cycle.

最后,我还尝试为Index明确实施Trait

pub trait Trait {
    type Associated;
}

impl<T: Trait> Index<T::Associated> for T {
    type Output = str;

    fn index(&self, associated: T::Associated) -> &'static str {
        "sup"
    }
}

不幸的是,它也失败了:

  
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`)
 --> src/main.rs:7:1
  |
7 | impl<T: Trait> Index<T::Associated> for T {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
  |
  = note: only traits defined in the current crate can be implemented for a type parameter

我想在这里做些不合理的事吗?有没有办法实现类似的东西,而不必使用泛型?

Playground

2 个答案:

答案 0 :(得分:11)

你很近,非常接近。

Trait并未假定其定义中对Trait的任何引用都是指当前类型。毕竟,您可以参考同样实施Trait的其他类型。

为了指定您想要特定类型,您应该注意编译器注意:使用<Type as Trait>::Associated,其中Type是当前类型。

定义Trait时,如何引用实例化的具体类型?您使用Self

解决方案是:

pub trait Trait: Index<<Self as Trait>::Associated> {
    type Associated;
}

答案 1 :(得分:1)

我认为以下内容提供了您想要的语义,并采用了第二次尝试的方法。

pub trait Trait {
    type Associated;
}

impl<T> Index<T> for Trait<Associated = T> {
    type Output = str;

    fn index(&self, associated: T) -> &'static str {
        "sup"
    }
}