Conflicting implementations of trait From

use std::marker::PhantomData;

trait Origin {
    const ORIGIN: i32;
}

struct Zero;
impl Origin for Zero {
    const ORIGIN: i32 = 0;
}

struct Hundred;
impl Origin for Hundred {
    const ORIGIN: i32 = 100;
}

struct Value<ORIGIN> {
    x: i32,
    origin: PhantomData<ORIGIN>,
}

impl<ORIGIN1: Origin, ORIGIN2: Origin> From<Value<ORIGIN1>> for Value<ORIGIN2> {
    fn from(v: Value<ORIGIN1>) -> Self {
        Self {
            x: v.x,
            origin: PhantomData,
        }
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0119]: conflicting implementations of trait `From<Value<_>>` for type `Value<_>`
  --> src/lib.rs:22:1
   |
22 | impl<ORIGIN1: Origin, ORIGIN2: Origin> From<Value<ORIGIN1>> for Value<ORIGIN2> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T> From<T> for T;

For more information about this error, try `rustc --explain E0119`.
error: could not compile `playground` due to previous error

I have already found this issue but is there any clear way forward that may allow the case where ORIGIN1 != ORIGIN2?

There are no negative trait bounds or type inequalities in the (stable) language. You could invent your own trait instead of using From, or just write an inherent method instead.

I went with the inherent method way. But why this case is not being separately considered where the generic parameter types are not the same?

I'm not sure what you mean by that. The compiler can't just assume they are not the same, because nothing in the impl implies that, if this is what you were thinking.

Sorry, if I have been unclear. What I meant to say is that there should be a syntax to specify that the two types are not the same. Like:

impl<ORIGIN1: Origin, ORIGIN2: Origin> From<Value<ORIGIN1>> for Value<ORIGIN2>
where ORIGIN1 != ORIGIN2,
{
    fn from(v: Value<ORIGIN1>) -> Self {
        Self {
            x: v.x,
            origin: PhantomData,
        }
    }
}

I think this is sound, although I am not much familiar with Rust soundness rules. Is there any plan to implement such functionality in some form or other?

I'm not sure if there is something like that planned; you can search on IRLO or on the Rust-lang RFCs GitHub repository for candidate proposals, if any.

It's an old idea:

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.