Skip to content

Commit ea62f9b

Browse files
authored
Rollup merge of rust-lang#61665 - aschampion:slice-eq-ptr, r=sfackler
core: check for pointer equality when comparing Eq slices Because `Eq` types must be reflexively equal, an equal-length slice to the same memory location must be equal. This is related to rust-lang#33892 (and rust-lang#32699) answering this comment from that PR: > Great! One more easy question: why does this optimization not apply in the non-BytewiseEquality implementation directly above? Because slices of non-reflexively equal types (like `f64`) are not equal even if it's the same slice. But if the types are `Eq`, we can use this same-address optimization, which this PR implements. Obviously this changes behavior if types violate the reflexivity condition of `Eq`, because their impls of `PartialEq` will no longer be called per-item, but 🤷‍♂ . It's not clear how often this optimization comes up in the real world outside of the same-`&str` case covered by rust-lang#33892, so **I'm requesting a perf run** (on MacOS today, so can't run `rustc_perf` myself). I'm going ahead and making the PR on the basis of being surprised things didn't already work this way. This is my first time hacking rust itself, so as a perf sanity check I ran `./x.py bench --stage 0 src/lib{std,alloc}`, but the differences were noisy. To make the existing specialization for `BytewiseEquality` explicit, it's now a supertrait of `Eq + Copy`. `Eq` should be sufficient, but `Copy` was included for clarity.
2 parents 35cacbc + d482589 commit ea62f9b

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

src/libcore/slice/mod.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -5342,13 +5342,24 @@ impl<A, B> SlicePartialEq<B> for [A]
53425342
return false;
53435343
}
53445344

5345-
for i in 0..self.len() {
5346-
if !self[i].eq(&other[i]) {
5347-
return false;
5348-
}
5345+
self.iter().zip(other.iter()).all(|(x, y)| x == y)
5346+
}
5347+
}
5348+
5349+
// Use an equal-pointer optimization when types are `Eq`
5350+
impl<A> SlicePartialEq<A> for [A]
5351+
where A: PartialEq<A> + Eq
5352+
{
5353+
default fn equal(&self, other: &[A]) -> bool {
5354+
if self.len() != other.len() {
5355+
return false;
5356+
}
5357+
5358+
if self.as_ptr() == other.as_ptr() {
5359+
return true;
53495360
}
53505361

5351-
true
5362+
self.iter().zip(other.iter()).all(|(x, y)| x == y)
53525363
}
53535364
}
53545365

@@ -5457,7 +5468,7 @@ impl SliceOrd<u8> for [u8] {
54575468
#[doc(hidden)]
54585469
/// Trait implemented for types that can be compared for equality using
54595470
/// their bytewise representation
5460-
trait BytewiseEquality { }
5471+
trait BytewiseEquality: Eq + Copy { }
54615472

54625473
macro_rules! impl_marker_for {
54635474
($traitname:ident, $($ty:ty)*) => {

0 commit comments

Comments
 (0)