By "core trait" I mean many of the traits listed in https://rust-lang-nursery.github.io/api-guidelines/interoperability.html
In particular, that means std traits like:
- Copy
- Clone
- Eq
- PartialEq
- Ord
- PartialOrd
- Hash
- Debug
- Display
- Default
and serde traits:
Even if Rust embraced incoherence and there were no orphan rules, you still wouldn't be able to write orphan impls for most of these traits, because their implementations need to access all private fields in order to be semantically correct. Even #[derive(...)]s for these traits wouldn't work for that reason.
In the special case of Serialize and Deserialize, there's an additional reason. It's often expected that the serialized form of a type will be forward compatible with all future versions of that type. In other words, if you serialize Foo from crate foo v1.0 and many months later deserialize it into a Foo from crate foo v1.5, that should "just work". That's basically impossible to guarantee unless crate foo is in charge of providing the Serialize and Deserialize impls.
Aside from std and serde, it's very rare for a trait to need access to all fields just to be semantically correct.
So, that's why an API Guideline to tell everyone to provide impls probably is the best possible solution, at least for these particular traits.
I believe this is the biggest cause of "red herring"/"XY problem" complaints about the orphan impls, i.e. complaints that changing the orphan impls actually wouldn't solve at all.
By "core trait" I mean many of the traits listed in https://rust-lang-nursery.github.io/api-guidelines/interoperability.html
In particular, that means
stdtraits like:and
serdetraits:Even if Rust embraced incoherence and there were no orphan rules, you still wouldn't be able to write orphan impls for most of these traits, because their implementations need to access all private fields in order to be semantically correct. Even
#[derive(...)]s for these traits wouldn't work for that reason.In the special case of
SerializeandDeserialize, there's an additional reason. It's often expected that the serialized form of a type will be forward compatible with all future versions of that type. In other words, if you serializeFoofrom cratefoov1.0 and many months later deserialize it into aFoofrom cratefoov1.5, that should "just work". That's basically impossible to guarantee unless cratefoois in charge of providing theSerializeandDeserializeimpls.Aside from
stdandserde, it's very rare for a trait to need access to all fields just to be semantically correct.So, that's why an API Guideline to tell everyone to provide
impls probably is the best possible solution, at least for these particular traits.I believe this is the biggest cause of "red herring"/"XY problem" complaints about the orphan impls, i.e. complaints that changing the orphan impls actually wouldn't solve at all.