profile
viewpoint

Ask questionsInvalid collision with TryFrom implementation?

Sorry for the code dump. This is the smallest code I could make to reproduce the problem.

use std::marker::PhantomData;
use std::convert::TryFrom;

trait Integer {}
impl Integer for u8 {}

trait Adapter<I: Integer>: TryFrom<I> + Into<I> {}

enum Choice {
    Foo,
    Bar,
    Baz
}

impl From<Choice> for u8 {
    fn from(c: Choice) -> u8 {
        match c {
            Choice::Foo => 1,
            Choice::Bar => 2,
            Choice::Baz => 3,
        }
    }
}

impl TryFrom<u8> for Choice {
    type Error = ();
    fn try_from(i: u8) -> Result<Choice, ()> {
        match i {
            1 => Ok(Choice::Foo),
            2 => Ok(Choice::Bar),
            3 => Ok(Choice::Baz),
            _ => Err(()),
        }
    }
}

impl Adapter<u8> for Choice {}

struct Pick<I: Integer, A: Adapter<I>> {
    phantom: PhantomData<A>,
    value: I,
}

impl<I: Integer, A: Adapter<I>> From<A> for Pick<I, A> {
    fn from(a: A) -> Pick<I, A> {
        Pick {
            phantom: PhantomData,
            value: a.into(),
        }
    }
}

impl<I: Integer, A: Adapter<I>> TryFrom<Pick<I, A>> for A {
    type Error = A::Error;

    fn try_from(p: Pick<I, A>) -> Result<A, Self::Error> {
        A::try_from(p.value)
    }
}

Attempting to compile this produces:

error[E0119]: conflicting implementations of trait `std::convert::TryFrom<Pick<_, _>>`:
  --> src/main.rs:53:1
   |
53 | impl<I: Integer, A: Adapter<I>> TryFrom<Pick<I, A>> for A {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T, U> std::convert::TryFrom<U> for T
             where T: std::convert::From<U>;

error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g. `MyStruct<A>`)
  --> src/main.rs:53:1
   |
53 | impl<I: Integer, A: Adapter<I>> TryFrom<Pick<I, A>> for A {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `A` must be used as the type parameter for some local type
   |
   = note: only traits defined in the current crate can be implemented for a type parameter

I've spent several hours looking at this and I can't figure out why I'm getting these errors. The type parameter A is being used as the type parameter for a local type. Maybe the compiler can't tell because it is nested inside TryFrom<>?

But I'm also not sure why the first error occurs at all. The rule it conflicts with can basically be described as "types with infallible conversions implicitly implement fallible conversions." But in my case there is no infallible conversion. So I don't see where the conflict is arising from.

If there is really a bug and I'm not just overtired, this may impact #49305.

rust-lang/rust

Answer questions jean-airoldie

This is is due to this core blanket implementation. Since it is possible that a type implement both the core Into<T> bound as well as your custom trait bound, this create a potential implementation conflict that the compiler can't allow.

Not sure how to circumvent this without negative trait bounds.

edit: Updated outdated link

useful!

Related questions

Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 2
using 'cargo install xsv' on windows 10 triggers rustc internal error hot 1
chain() make collect very slow hot 1
if/while Some(n) = &mut foo sugar will leak a temporary mutable borrow to current scope in particular situation hot 1
build an empty project failed (undefined reference to `__onexitbegin') hot 1
Crater runs for Rust 1.38.0 hot 1
Spurious NaNs produced by trig functions with valid inputs on Windows GNU toolchains hot 1
under latest MinGW, cannot link with C code using stdout hot 1
Archive all nightlies hot 1
Building LLVM with Clang fails hot 1
Internal compiler error: can't buffer lints after HIR lowering hot 1
E0373 help suggests `move async` but the correct syntax is `async move` hot 1
Tracking issue for `Option::contains` and `Result::contains` hot 1
async fn + rustfmt don't "just work" inside of RLS hot 1
Include images in rustdoc output hot 1
Github User Rank List