Understanding conflicting blanket implementation when a new candidate is defined
⚓ Rust 📅 2025-10-03 👤 surdeus 👁️ 6Hello! Sorry if this is a common question; it's a bit hard to search...
I am struggling to find a properly substantiated explanation (not just a guess) as to why the following happens:
Consider this:
struct Wrapper<T>(T);
trait E {}
impl<A, B> From<A> for Wrapper<B>
where
A: Into<B> + E,
{
fn from(value: A) -> Self {
Self(value.into())
}
}
struct X {}
impl E for Wrapper<X> {}
struct Y {}
impl E for Wrapper<Y> {}
fn main() {}
This does not compile:
error[E0119]: conflicting implementations of trait `From<Wrapper<_>>` for type `Wrapper<_>`
--> src/main.rs:4:1
|
4 | / impl<A, B> From<A> for Wrapper<B>
5 | | where
6 | | A: Into<B> + E,
| |___________________^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
I assume it's considering the possibility where, in the context of the blanket implementation, for some type U, A = Wrapper<U> and B = U; thus the implementation looks like impl<U> From<Wrapper<U>> for Wrapper<U>, which conflicts with the core implementation of impl<T> From<T> for T (T = Wrapper<U>).
But then, the actual question: why does it compile if one removes the line impl E for Wrapper<Y> {}, so there is only one implementation of E for a concrete type (X), or both of them?
-
Compiles;// impl E for Wrapper<X> {} // impl E for Wrapper<Y> {} -
Compiles;impl E for Wrapper<X> {} // impl E for Wrapper<Y> {} // or vice-versa -
Does not compile.impl E for Wrapper<X> {} impl E for Wrapper<Y> {} // or more
How are cases 2 and 3, in particular, different? Does having two distinct types implementing that same trait somehow enable an overlap that does not occur with only one and I'm not seeing? Is the compiler analyzing generally different things in one case vs the other?
1 post - 1 participant
🏷️ Rust_feed