Motivate the orphan rule

My understanding of the orphan rule is that if we have:

impl Bark_T for Dog

it must either be in the crate where Bark_T is defined or in the trait where Dog is defined.

This has been the bane of my attempts at parallelizing builds. Can someone motivate the existence of this rule?

What would be so bad if we got rid of it, and then, at link time, had a "yo, you have conflicting impl Bark_T for Dog" detector ?

The conflict may not be known until much later, for a crate that has nothing to do with either. Crates A and B may be fine together, as well as A and C, as long as they're not all together. But way down in crate Z they've ended up with a dependency tree that includes all three, and they'll get your error with nothing they can do about it.

That may happen across time too. Suppose A, B, and C do all work together in Z. Then B adds some impls in an update, which works fine for them, but now Z breaks.

2 Likes

I don't understand this argument here. I think you're saying: this can't be detected until link time.

However, I'm wondering: why is it so bad if this is detected only at link time?

It would be very annoying if you couldn't depend on some two crates at the same time (or two versions of the same crate!).

Another issue is that if you implement impl Bark for Dog, and then later the author of the dog crate also implements Bark for Dog (in a minor semver revision!), your code now stops compiling and you have no easy way to fix it.

1 Like

Because it would be a semver hazard, and a time bomb for the ecosystem. It's very valuable that crates can be freely composed, and that they can provide reasonable stability guarantees. Without orphan rules, neither of that is true, since an unrelated crate could add an impl which breaks your entire build.

9 Likes

RFCs 1023 and 2451 have motivation sections (and links to other documents) that explore the challenges more thoroughly.

Incidentally the rules are a bit more nuanced than "own the trait or own the type".

5 Likes