The general idea behind orphan rules is that conflicting implementations must be forbidden. If crate a is used in crates b and c, and crate a defines a type Foo and a trait Bar, then crate b must not create an impl Bar for Foo: If it could do this, then crate c could do the same thing; ultimately a crate d depending on both b and c would see two conflicting implementations.
That’s why impl ExternalTrait for ExternalType are forbidden. The other cases can’t produce this problem: at least in a world without generics, for every impl there’s always only exactly one crate that could create that impl: If a trait Bar and type Foo are defined in the same crate, only that crate can impl the trait for the type, i.e. impl Bar for Foo. If they’re defined in different crates, then impl Bar for Foo can only be in one of the two crates, depending on which one of the crates depends on the other. Cyclic dependencies are impossible, so two conflicting impls are ruled out; if neither crate depends on the other, nobody can write an impl Bar for Foo.