Associated types with the same name

struct Unit;

trait A {
    type MyType;
}

trait B {
    type MyType;
}

impl A for Unit {
    type MyType = i32;
}

impl B for Unit {
    type MyType = f32;
}

trait C: A + B {}

impl C for Unit {}

fn main() {
    let unit: Box<dyn C<**/* what to put here*/**>> = Box::new(Unit);
}

How do I specify MyType from both A and B?

Those are distinct types regardless of the identical name, so it would be quite strange to be able to refer to them both at the same time.

AFAICT from that it follows that such traits are not object-safe.

I should be able to prefix them like A::MyType and B::MyType. No?

Each separately is addressable as <Type as Trait>::AssocItem i.e. <Unit as A>::MyType and <Unit as B>::MyType.

However, MyType is ambiguous for trait C: which of the 2 associated types does <Unit as C>::MyType refer to?
impl A for Unit and impl B for Unit offer conflicting definitions for that name.
That is why I think you cannot convert such values to use dynamic dispatch i.e. trait C is not object-safe.

not a valid syntax in this case

So you can't combine two traits with the same name for the associated types?
This appears to be a strange oversight on the part of the rust team.
At the very least, you should be able to alias them.

I fiddled with your example and found a workaround where we'd give two generic parameters to C which are used to define A::MyType and B::MyType on the implementation of C for Unit:

struct Unit;

trait A {
    type MyType;
}

trait B {
    type MyType;
}

impl A for Unit {
    type MyType = i32;
}

impl B for Unit {
    type MyType = f32;
}

trait C<T, U>: A<MyType=T> + B<MyType=U> {}

impl C<i32, f32> for Unit {}

fn main() {
    let unit: Box<dyn C<_, _>> = Box::new(Unit);
}

It is a little inconvenient but compiles on the playground. I wonder if there is a better way, but I was not able to find it.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.