I am apparently misreading what the Eq trait does when I declare it to be derived on a struct. What I am trying to achieve is that an instance of the struct is equal to itself, but not equal to another instance even if all the fields are identical. I got that PartialEq would not do that. But when I tried adding Eq, it was still trying to apply it to the intdividual fields. Wo what is Eq trying to do? And how to do I get the goal I am after?
Thanks,
Joel
It doesn't change what the PartialEq implementation does, it just gives a logical[1] guarantee about how that implementation behaves: comparing a value to itself will result in PartialEq::eq returning true. (That says nothing about what happens when different values are compared.)
Note that Rust doesn't have an inherent "object identity". You can approximate it somewhat by looking at addresses, but there are edge cases involving zero-sized types and the like. (I'll add a demonstration in a minute.)
With that caveat out of the way: Implement PartialEq<Self> directly with the behavior you want.
unsafecannot rely on it for soundnes ↩︎
For example, you can implement Eq&PartialEq with object-identity-like behavior as follows:
use std::{cmp, ptr};
struct Foo {
field: u8, // let’s make sure `Foo` it not zero size by having some field :-)
}
// define the behavior of `==` operator for `Foo`
// (the behavior of `!=` is automatically derived from this by negation)
// the generic argument can be left out, i.e. `PartialEq` below
// is short for `PartialEq<Self>` because `pub trait PartialEq<Rhs = Self>`
// is declared with this `= Self` default-argument in the standard library
impl cmp::PartialEq for Foo {
fn eq(&self, other: &Self) -> bool {
// both arguments are implicitly cast to `*const Foo`
// when passed to `ptr::eq`, which then compares the
// pointer addresses and hence the “identity”
ptr::eq(self, other)
}
}
// `==` implemented as above is not only transitive and symmetric
// but also reflexive, so we can implement `Eq` too
// (in fact, it’s fairly uncommon that some `==` operation *does* fulfill
// the former but *not* the latter requirements – the types `f32` and `f64`
// are actually pretty weird in this regard, and more an exception than the norm)
impl Eq for Foo {}
Thanks. Got that part to compile. Now back to the hard parts. (Probably going to need to figure out Interior Mutability and Weak References so database entries can reference the parent database anchor without owning that parent.)