Ixrec / rust-orphan-rules

An unofficial, experimental place for documenting and gathering feedback on the design problems around Rust's orphan rules
Apache License 2.0
200 stars 3 forks source link

Coherence and Orphan Rules in Rust

This repo is an unofficial, experimental attempt to explain the design challenges of coherence and the orphan rules in Rust, and provide clear places where the community can aggregate specific kinds of feedback on this complex issue (inspired by and suggested on this internals thread). We do not expect any prior knowledge of type theory or other programming languages; if you know most of what's in The Book, then everything here should make sense (if not, please open an issue).

Discussion on this repo might lead to PRs to improve compiler diagnostics, the development of third-party crates, the drafting of new RFCs, convincing everyone that the status quo is the least of many evils, or merely providing a convenient link the next time someone asks about these problems. Any of those would be considered a success.

What is Coherence?

In Rust, "trait coherence" (or simply "coherence") is the property that there is at most one implementation of a trait for any given type.

Any programming language that has a feature like traits or interfaces must either:

Rust chooses to enforce coherence.

What's wrong with incoherence?

We could provide some kind of disambiguation syntax like <Type as Trait using impl from Crate>::method() if we wanted to support incoherence. But there are deeper problems with incoherence than the need for some funky syntax:

What are the Orphan Rules?

Rust enforces trait coherence through two sets of rules:

The precise statement of the orphan rules is rather technical because of generics like impl Trait<Foo, Bar> for Type<Baz, Quux> (see "Little Orphan Impls"), and the #[fundamental] attribute, and OIBITs/auto traits, and probably something else I'm forgetting about. Today, I believe the most official and up to date precise statement of the orphan rules is RFC #2451, accepted in October 2018 and implemented in January 2019.

Most Rustaceans stick to the simplification that "either the type or trait must be from the same crate" since it's very easy to remember and is accurate in the most typical cases.

Why are the Orphan Rules controversial?

In short: there are a lot of impls that people want to write, but they currently cannot write because of these rules.

This is where things get interesting, and where we want your input.

In many cases this desire is an "XY problem", and there's actually a much better solution that doesn't involve anyone writing an orphan impl. I'm hoping this repo can help clarify which use cases are XY problems, which are merely theoretical and which are genuine pain points. I suspect that alone will make it obvious what, if anything, Rust should change.

That's all the high-level cases I'm aware of. If I missed something, please open an issue.

Miscellaneous

https://github.com/Ixrec/rust-orphan-rules/issues/1 is a timeline of Rust RFCs, issues and blog posts relevant to the orphan rules, with many links

https://github.com/Ixrec/rust-orphan-rules/issues/9 describes how other languages handle these issues

License

This repository is licensed under either of

at your option.

Contributions

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.