Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

rust - How do I bound a trait with a supertrait that uses the trait's associated type as a parameter?

I have a trait Trait with an associated type Trait::Associated. I am trying to bound the trait by requiring that it be indexable by its associated type, as shown here:

use std::ops::Index;

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

However, the compiler complains that the associated type is ambiguous

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`

I also tried referring to the associated type as Self::Associated, but then the compiler protests about a cyclic reference between the type and the trait:

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.

Finally, I also tried explicitly implementing Index for 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"
    }
}

Unfortunately that fails too:

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

Am I trying to do something unreasonable here? Is there a way of achieving something similar, without having to use generics?

Playground.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are close, very close.

The Trait does not assume that any reference to Trait in its definition refers to the current type. After all, you could wish to refer to other types also implementing Trait.

In order to specify that you want a specific type, you should heed the compilers note: use <Type as Trait>::Associated, where Type is the current type.

When defining the Trait, how do you refer to the concrete type for which it will be instantiated? You use Self!

The solution is:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...