Revisit Orphan Rules

As mentioned above, the solution proposed by @nikomatsakis would allow for such situations. Crate B can use annotated types indicating that they must use the implementation provided in crate B. In addition, the default rules would automatically defer to the implementation within crate B, so it is backwards-compatible with crate B as it exists now.

The type-specification comes in if some crate C tried to override that implementation. The whole point of this would be that this would be allowed. The compiler would kick back an error in the cases of ambiguous implementations and they would be disambuguated just like namespacing overlapping function definitions are now. I don’t see why impls should be treated differently than overlapping function definitions, which are currently allowed and disambiguated using namespaces.

This allows, for example, some crate A to do some unsafe stuff depending on a locally-defined impl, crate B to also do some unsafe stuff depending on a locally-defined impl, and then crate C to come along and use both by saying something like this:

let a: S:A::T = {...} //uses impl T for S from A
let b: S:B::T = {...} //uses impl T for S from B

An instance where this might result in trouble is if you pass a to some function in crate B, such as

fn do_unsafe_stuff_assuming_local_impl(s: S) {
   //---snip---
}

This would have to be changed to

fn do_unsafe_stuff_assuming_local_impl(s: S:self::T) {
   //---snip---
}

(or something similar) in which case passing a would now fail.

Again - this would not possibly impact any existing crates, because such issues only kick in when ambiguity arises, which (due to the orphan rule) does not currently occur. Situations like this are easy to detect, and we could implement a compiler warning.