Conflict in generic implementation of trait From<T>

We can implement trait From for a newtype with concrete raw type in below way.

struct Wrap(i32);

// For all T that can be converted into i32, now can be converted into Wrap as well.
impl<T> From<T> for Wrap where T: Into<i32>
{
    fn from(v: T) -> Self
    {
        Self(v.into())
    }
}

fn main()
{
    let w = Wrap::from(2);
    println!("{}", w.0);
}

If we intend to implement a similar trait for a generic newtype. It will failed due to implementation conflicts.

struct Wrap<T>(T);

impl<T,U> From<U> for Wrap<T> where U: Into<T>
{
    fn from(u: U) -> Self
    {
        Self(u.into())
    }
}

fn main()
{
//    let w = Wrap::<i32>::from(Wrap(2));
    let w = Wrap::<i32>::from(2);
    println!("{}", w.0);
}

The conflict is about another default implementation in core with impl<T> From<T> for T. And to above Wrap, the core implementation of trait From accept input type of Wrap itself and output a new Wrap.

Our implementation above provide implementation of From (and U satisfy Into as the generic constrait). U may represent Wrap itself, and Wrap could be converted into T (for example, by exact the Self.0 and output it directly).

Then, the compiler has confused which is the true logic we want to build for this trait.

Is there any possible way that we can work through in the generic newtype case?

I might be wrong, but specialization might allow such conflicting implementations to coexist.

Only if the specializing implementation is less general than the specialized implementation. This is not the case here. As the specializing implementation doesn't have a T: Into<i32> bound.

2 Likes

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.