Skip to content

Invalid collision with TryFrom implementation? #50133

Description

@npmccallum

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions