Description
(Originally reported in this comment in #31844)
In the following, we have a Child
trait to represent a "parent-child" relationship between two types. Alice
is a child of ()
and Bob
is a child of Alice
. Then, we have a trait Foo
that we want to implement for Alice
, and for all types that are children of a Foo
(so Alice
and Bob
should both implement Foo
):
#![feature(specialization)]
trait Child {
type Parent;
}
struct Alice;
impl Child for Alice {
type Parent = ();
}
struct Bob;
impl Child for Bob {
type Parent = Alice;
}
trait Foo { fn foo(&self); }
impl Foo for Alice {
fn foo(&self) { println!("Alice foo!"); }
}
// Implement for all children with parents that implement `Foo`
impl<T> Foo for T
where T: Child, T::Parent: Foo
{
default fn foo(&self) { println!("Descendant foo!"); }
}
fn main() {
Alice.foo();
Bob.foo();
}
(playpen)
Expected output
The program should print "Alice foo!" and "Descendant foo!"
Actual output
The program fails to compile:
error[E0119]: conflicting implementations of trait `Foo` for type `Alice`:
--> <anon>:28:1
|
23 | impl Foo for Alice {
| - first implementation here
...
28 | impl<T> Foo for T
| ^ conflicting implementation for `Alice`
error: aborting due to previous error
Version info
$ rustc --version
rustc 1.13.0-nightly (55bf6a4f8 2016-09-18)
Other notes
There are two workarounds I've found to fix the error above.
The first is to just remove the T::Parent: Foo
clause (which works in this case, but not so much for my actual usecase).
The second workaround is to introduce another trait, FooChild
, which is implemented for all types where Self::Parent: Foo
. We can then use FooChild
in the where
clause instead:
trait FooChild { }
impl<T> FooChild for T
where T: Child, T::Parent: Foo
{
}
// Implement for all children with parents that implement `Foo`
impl<T> Foo for T
// where T: Child, T::Parent: Foo
where T: FooChild
{
default fn foo(&self) { println!("Descendant foo!"); }
}
// ...
(playpen)
Interestingly, the second workaround doesn't work when Child
is moved into a separate crate (example repo)