Conflicting trait implementation


When compiling the following code, where both the trait and the type are in the same crate:

trait Foo<T> {
    fn val(&self) -> T;

struct Bar<T> { val: T }

impl<T, F> From<F> for Bar<T> where F: Foo<T> {
    fn from(t: T) -> Self {
        Self { val: t.val() }

the compiler gives me the following error:

error[E0119]: conflicting implementations of trait `std::convert::From<Bar<_>>` for type `Bar<_>`
 --> src/
7 | impl<T, F> From<F> for Bar<T> where F: Foo<T> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: conflicting implementation in crate `core`:
          - impl<T> From<T> for T;
  = note: downstream crates may implement trait `Foo<_>` for type `Bar<_>`

Given the orphan rule, how could another crate (downstream crate ??) implement Foo for type Bar ?
I missed something. Could someone enlighten me ?

Thanks for your help

Yes, a downstream crate can implement Foo<Baz> for Bar<T> as long as Baz is a local type in the downstream crate.

Trait Implementation Coherence

A trait implementation is considered incoherent if either the orphan rules check fails or there are overlapping implementation instances.

Two trait implementations overlap when there is a non-empty intersection of the traits the implementation is for, the implementations can be instantiated with the same type.

Orphan rules

Given impl<P1..=Pn> Trait<T1..=Tn> for T0 , an impl is valid only if at least one of the following is true:

  • Trait is a local trait
  • All of
    • At least one of the types T0..=Tn must be a local type. Let Ti be the first such type.
    • No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti )

Only the appearance of uncovered type parameters is restricted. Note that for the purposes of coherence, fundamental types are special. The T in Box<T> is not considered covered, and Box<LocalType> is considered local.

For an impl<T> Foo<Baz> for Bar<T>, Foo is not a local trait, but
One of the types Bar<T>, Baz is local (namely, Baz is local)
and the type parameter T is covered in Bar<T>.

(If you don’t want to think about covered/uncovered type parameters, you can also just consider e.g. impl<T> Foo<Baz> for Bar<Baz>.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.