That could be problematic. What if you need a custom implementation for PartialEq
, but want to derive Eq (since it doesn't contain logic and can thus trivially be derived as long as the trait bounds are already correct)? The derive code would have to know whether the "lower trait" is implemented anywhere in the entire crate, which it probably doesn't/can't know. You could say that you have to implement it in these cases manually, of course.
This should be a logical error (especially in Ord/PartialOrd
).
In my design, if the trait is Eq
, you could just implement Eq
, which impl PartialEq
implictly.
Not that this struct has an impl Eq
, but if it did, the impl PartialEq
would exclude its dns_cache
field from the computation.
Prior art: In Kotlin, marking a class as data class automatically implements the equals()
, hashCode()
, toString()
, and copy()
methods, which is roughly equivalent to deriving PartialEq
, Hash
, Debug
, and Clone
in Rust.
It would be nice to have the same in Rust in a more ergonomic way, but I think the best way to get there is with reflection. If we add #[data]
(which would have the same effect as Kotlin's data class
, but also allow reflection), it could also enable blanket implementations for various 3rd party traits such as Serialize
, Deserialize
, Arbitrary
, etc.
// in crate `serde`
impl<T: Data> Serialize for T {
// implemented via reflection
}
// in your library
// `MyStruct` implements the `Data` trait, so it automatically gets a `Serialize` implementation
#[data]
pub struct MyStruct { .. }