Disambiguating associated types from super traits in a trait object
Suppose you have a trait:
trait Foo: std::ops::Index<usize> + std::ops::Index<isize> {}
How do you declare a Foo trait object, say a Box? The Output associated types need to be specified but they need to be disambiguated between the two super traits. Projections that I’ve tried don’t seem to work but it’s possible I didn’t try the right incarnation.
This stems from the https://users.rust-lang.org/t/how-to-specify-associated-types-with-same-name-in-generics/15677 post.
The trait system is pretty broken on all fronts. I hope it gets overhauled completely when HKT comes along.
Ricky Han at 2018-03-23 09:44:16
Triage: I'm not aware of a way to do this.
Steve Klabnik at 2019-12-05 13:32:07
Repro from a duplicate issue:
trait Foo { type Error; } trait Bar { type Error; } trait Cake : Foo + Bar {} struct S { f: Box<Cake<Error = i32>>, } fn main() {}Oli Scherer at 2020-05-02 06:28:38
There's a similar disambiguation problem here:
trait A { type C; } trait B: A { type C; } struct S(Box<dyn B<C=()>>);though this is less of an issue because it's unlikely
Bwould be defined this way in practice.Lily Chung at 2020-05-05 22:48:18
It's possible to work around this by defining an intermediate trait (thanks @estebank):
trait Foo { type Error; } trait Bar { type Error; } trait Cake : Foo + Bar {} trait Cake2 : Cake where Self : Foo<Error = i32>, Self : Bar<Error = u64> {} struct S { f: Box<dyn Cake2>, }Lily Chung at 2020-05-05 23:22:31
Here's a somewhat complete example of how the above could work (without having to add implementations for
Cake2for every relevant type):impl<T> Cake2 for T where T: Cake + Foo<Error = i32> + Bar<Error = u64> {}Esteban Kuber at 2020-05-05 23:35:39
The error messages about these kind of things are also pretty bad: #100109
Jendrik at 2023-03-20 07:47:18