Rust's orphan rules don't allow it. The exact covering semantics are complicated (if you're interested, this article is a good jumping-off point), but the basic idea is this:
Take all of the type and trait names passed to an impl
in order, starting with the trait itself, then to the structure or enum we're writing an impl
for, then any type arguments. So with the impl
written as
impl<T> MyTrait<Bar, Baz, T> for Foo
we would write MyTrait, Foo, Bar, Baz, T
(where T
is a type variable).
Now, in this list we've written, find the first name that is defined in our own crate. If the trait is defined in our own crate, then that's the name. If Foo
is, then take that one. Otherwise, keep going until you find one. If there are no names defined in the current crate, fail because we have an orphan instance. In this example, let's pretend MyTrait
is defined somewhere else but Foo
is our own. Then we have
MyTrait, Foo, Bar, Baz, T
^^^
Anything before the name we just found must be concrete, i.e. it can't be a generic type argument. In our example here, the only type argument is T
, and it occurs after Foo
, so it's fine.
(Note that I'm also glossing over covered types. That is, an impl on &Foo
is, for the orphan purposes, considered an impl on Foo
. This applies to references, Box
, and several other built-in Box
-like types; it never applies to types you define yourself)
Now let's take a look at your examples. Things get more complicated when we add generics, and I'm not going to go over all of the messy technical details here, so we'll try to keep it as simple as possible.
impl<T: A> From<T> for B<T>
Here, the trait is From
, the type we're implementing is B
, and our type argument to From
is T
. Our list is
From, B, T
Note that although we're implementing for B<T>
, we say T
is covered by the B
type, so we only take the top-level B
, not what's inside.
Now From
is standard library, so we don't own it, but B
is in our crate. So we have
From, B, T
^
Then we look for generic arguments. The only type argument here is T
, and it appears after the B
that we own, so we're good.
Now the other one.
impl<T: A> From<B<T>> for T
The trait is From
, as before. The first type is T
, a generic type argument. Then B<T>
is next.
From, T, B
Again, we write B
, not B<T>
, since we only care about uncovered types.
From
is standard library, and T
is a type argument, so B
is the only thing we own here.
From, T, B
^
But there's a type argument T
before the first thing we own! That's a problem, so this fails by Rust's orphan rules.
The reason the rules are written this way is to prevent two sibling crates (i.e. crates who are not aware of each other) from accidentally implementing conflicting instances. If we allowed
impl<T: A> From<B<T>> for T
then someone else might come along one day and write
impl<T> From<T> for C
for some type C
in their own crate. They're well within their rights to do so: C
is their own type and the only generic argument occurs after C
in their trait argument list. But then there are two candidate solutions for impl From<B<C>> for C
. (Note that trait bounds, i.e. T: A
are taken into consideration much later and are not considered at this point, since that would just make the already complex problem of trait resolution completely untenable).