Associated trait specialization and trait objects


#1

The following code:

`
pub trait assoc {
type X;
}

pub trait sub : assoc<X=i32> {}

type C = sub;
`

complains about sub missing the type parameter X (note that C should be the trait object sub).

  1. Why does sub inherit assoc’s X here when it is specified directly?
  2. How is it possible to have a trait inheriting from a specialized associated type like this?

#2

I can answer the first question, I don’t know if I can provide all the details for the second.

For starters:

The trait sub inherits assoc's associated item because anything implementing sub has to implement assoc, and thus has to provide some type X to associated with it.

The second bit:

The problem you are running into, in a simpler snippet, is this being not allowed:

trait TheTrait { type Assoc; }
type Alias = TheTrait;

I believe this is due to Alias the not including all of the information. See this bigger example:

trait TheTrait {
    type Assoc;
    
    fn get_assoc(&self) -> Self::Assoc;
}

type Alias = TheTrait;

fn uses_alias(thing: &Alias) {
    let x = thing.get_assoc();
    // what type is `x`...? How can we know?
}

Like the comment suggests, when using Alias like that, there is no way to know what the associated type is.

To fix this, we need to either specify a specific associated type for the alias:

type Alias = TheTrait<Assoc=i32>;

Or specify that alias is generic for a T and specifies the associated type is that T:

type Alias<T> = TheTrait<Assoc=T>

With these, uses_alias can safely either know that get_assoc returns an i32, or specify another bound over T to know what it gets.


#3

First, thanks for the reply.

Secondly, if a trait inherits an associated trait with a specified type doesn’t it mean that it implements the associated trait with the same specified type?

In fact I’m not clear on why it would inherit the associated type at all - if you need the type from the inherited associated trait then why not just use ::assoc_type? And what would happen if multiple associated traits are inherited (or worse, if they have the same associated type names)?

Is there any motivation behind this design of a trait inheriting an associated trait also inheriting its associated types? It appears to me that they are generally unrelated traits with the only constraint being that an associated trait impl is guaranteed.


#4

Sorry I didn’t get back to this until now! Seems that I’m not getting notifications for this site, I just now realized there was another reply here.

To actually answer, I’m not sure why these design decisions were made. I’ve tried looking for an RFC introducing the type syntax, but I can’t seem to find it.

As far as I can tell, type aliases were designed mostly with concrete types in mind - there isn’t a clear reason that I can find not to just allow ::assoc_type as you say. There’s an RFC I did find for introducing something like type aliases but that are specific to traits, https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md, which may be a better solution for this though.