In general case, it is not possible to implement in crate C1 a trait defined in C2 for a Type defined in crate C3, being assumed that C1, C2, C3 are different
But is there a trick to designing a trait on purpose, so that such implementations are allowed?
No. There is no such thing, as it is fundamentally flawed because it allows collisions between impls.
For example, you can upgrade a minor version of a dependency, then your code won’t compile because in the minor version they added a dependency of their on some crate that had some impl for trait, and you already have a dependency that has a colliding impl.
There are some ways to relax coherence, but all are unstable and none are the same as what you want:
- Negative impls allow you to promise some trait will never be implemented for some type, allowing othwerise potentially overlapping impls – but does not affect the orphan checks at all;
- Fundamental types allow you to promise a type will not add a blanket impl, allowing you to impl foreign traits for type wrapped in them (this is the reason you can, for example, impl a foreign trait on
Box<LocalType>) – but does not allow to implement foreign traits on any type;
- Fundamental traits are traits that adding a blanket implementation for them is a breaking change (although the teams want to get rid of them). This is more general than negative impls (too general even, which is why they want to get rid of it), but still as far as I can tell only affects overlap check.