Here are some examples of ne
implementations that I could find in the standard library:
impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for Box<T, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(&**self, &**other)
}
#[inline]
fn ne(&self, other: &Self) -> bool {
PartialEq::ne(&**self, &**other)
}
}
Here a container type Box<T, A>
explicitly implements ne
, because the contained type could have a custom ne
implementation, and Box<T, A>
must properly delegate to it. A similar reason would exist for other wrapper types and smart pointers.
// core_simd::vector
impl<T, const LANES: usize> PartialEq for Simd<T, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
T: SimdElement + PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
// Safety: All SIMD vectors are SimdPartialEq, and the comparison produces a valid mask.
let mask = unsafe {
let tfvec: Simd<<T as SimdElement>::Mask, LANES> = intrinsics::simd_eq(*self, *other);
Mask::from_int_unchecked(tfvec)
};
// Two vectors are equal if all lanes tested true for vertical equality.
mask.all()
}
#[allow(clippy::partialeq_ne_impl)]
#[inline]
fn ne(&self, other: &Self) -> bool {
// Safety: All SIMD vectors are SimdPartialEq, and the comparison produces a valid mask.
let mask = unsafe {
let tfvec: Simd<<T as SimdElement>::Mask, LANES> = intrinsics::simd_ne(*self, *other);
Mask::from_int_unchecked(tfvec)
};
// Two vectors are non-equal if any lane tested true for vertical non-equality.
mask.any()
}
}
SIMD vectors use optimized instructions for comparison. The ISA provides separate instructions for equality and inequality, so the safe wrapper types should also use them.
There are also many cases where the ne
method is implemented for more guaranteed performance. For example, tuples explicitly say that all fields must be equal in the eq
impl, and at least one must be unequal in the ne
impl. The performance benefits are obvious. Technically the compiler could inline the eq
impl into the ne
impl and simplify the boolean expression. However, inlining can be quite unreliable, because it's based on heuristics, and because it works in a "bottom-up" way. If the impls of eq
for the tuple's components are inlined, the eq
impl for the tuple itself may become larger than some threshold and ineligible for inlining. This would penalize ne
for no good reason.