enum A {}
enum B {}
trait Identify {
type Id;
}
trait Something<T> {}
// This implementation...
impl<T, U> Something<T> for U
where
T: Identify<Id = A>,
{}
struct Local;
// ...conflicts with this one...
impl<T> Something<T> for Local
where
T: Identify<Id = B>, // even though T **cannot** be the same !
{}
which fails to compile:
error[E0119]: conflicting implementations of trait `Something<_>` for type `Local`
--> src/lib.rs:18:1
|
10 | / impl<T, U> Something<T> for U
11 | | where
12 | | T: Identify<Id = A>,
| |________________________- first implementation here
...
18 | / impl<T> Something<T> for Local
19 | | where
20 | | T: Identify<Id = B>, // even though T **cannot** be the same !
| |________________________^ conflicting implementation for `Local`
As indicated in the code comments, it surely can never be the case that the same T is used in the two impls, since it cannot have both Id = A and Id = B? So it seems that Rust is being overly pessimistic here.
Fortunately, in my real case, I don't actually need the firstSomething impl (for blanket U) to be generic over its type parameter T: I can instead make explicit implementations for particular concrete type parameters—and that does indeed solve the problem... so long as Local and its Something impl are in the same crate: playground.
Unfortunately, if Local and its Something impl are downstream (my real case) it continues to conflict with upstream blanket impls even if they use concrete type parameters and even if those parameters are explicitly constrained to implementing Identify<Id = A>:
error[E0119]: conflicting implementations of trait `crate1::Something<()>` for type `Local`
--> src/lib.rs:7:1
|
7 | / impl<T> Something<T> for Local
8 | | where
9 | | T: Identify<Id = B>,
| |________________________^
|
= note: conflicting implementation in crate `crate1`:
- impl<U> crate1::Something<()> for U
where <() as crate1::Identify>::Id == A, (): crate1::Identify;
This somewhat surprised me even though I assume this is a well understood limitation, but a quick search of the issue tracker didn't throw up any obvious candidates? Grateful for any pointers to existing discussion and/or suggested workarounds.