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);
}
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.
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.