Not understand Orphan Rule

struct Wrapper<T>(T);

impl<T> From<Wrapper<T>> for T {
    fn from(w: Wrapper<T>) -> Self {
        w.0
    }
}

The compiler will says

error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Wrapper<T>`)
 --> src/lib.rs:4:6
  |
4 | impl<T> From<Wrapper<T>> for T {
  |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Wrapper<T>`)
  |
  = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
  = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last

For more information about this error, try `rustc --explain E0210`.

I have learnt orphan rules before, but I don't understand this case. Shouldn't From<Wrapper<T>> be considered as a local trait, because it has a local type Wrapper<T>? If the compiler permits the above code to be compiled, what unsound things will happen?

Then I gave up using From and turned to using Into, but still failed.

struct Wrapper<T>(T);

impl<T> Into<T> for Wrapper<T> {
    fn into(self) -> T {
        self.0
    }
}
error[E0119]: conflicting implementations of trait `std::convert::Into<_>` for type `Wrapper<_>`
 --> src/lib.rs:4:1
  |
4 | impl<T> Into<T> for Wrapper<T> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<T, U> Into<U> for T
            where U: From<T>;

For more information about this error, try `rustc --explain E0119`.

Why are they conflicting? T is not implements From<Wrapper<T>>.

The T after for is uncovered, but it appears before the local type Wrapper<T>.

I think a user of your crate could add an impl<T> From<Wrapper<T>> for MyType<T> {} impl which would conflict with your impl<T> Into<T> for Wrapper<T> impl due to the impl<T, U> Into<U> for T where U: From<T> impl in the standard library and it would conflict with your original impl<T> From<Wrapper<T>> for T impl.

It makes sense. But what about the first impl From case?

I know, but why does this restriction exist?

Because if some other crate defines an impl From<Wrapper<MyType>> for MyType for some MyType local to that other crate, then it would overlap with your impl. The orphan rule must disallow one of them because impl blocks may not overlap, and in this case it is your impl that got disallowed.

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.