diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-07-11 04:33:11 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-11 04:33:11 +0200 |
| commit | ea62f9b3ecd00e1ad3cfbf5856117de21cc5dc38 (patch) | |
| tree | f3c471da6d44b5aba0a5fecf1631dcc62b797c26 | |
| parent | 35cacbce1661366250a877da4fa5b6b4cb03542e (diff) | |
| parent | d482589f292abda9a5c2895adf63189168f92a70 (diff) | |
| download | rust-ea62f9b3ecd00e1ad3cfbf5856117de21cc5dc38.tar.gz rust-ea62f9b3ecd00e1ad3cfbf5856117de21cc5dc38.zip | |
Rollup merge of #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 #33892 (and #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 #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.
| -rw-r--r-- | src/libcore/slice/mod.rs | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index fdf3cc8e006..363ae088275 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -5342,13 +5342,24 @@ impl<A, B> SlicePartialEq<B> for [A] return false; } - for i in 0..self.len() { - if !self[i].eq(&other[i]) { - return false; - } + self.iter().zip(other.iter()).all(|(x, y)| x == y) + } +} + +// Use an equal-pointer optimization when types are `Eq` +impl<A> SlicePartialEq<A> for [A] + where A: PartialEq<A> + Eq +{ + default fn equal(&self, other: &[A]) -> bool { + if self.len() != other.len() { + return false; + } + + if self.as_ptr() == other.as_ptr() { + return true; } - true + self.iter().zip(other.iter()).all(|(x, y)| x == y) } } @@ -5457,7 +5468,7 @@ impl SliceOrd<u8> for [u8] { #[doc(hidden)] /// Trait implemented for types that can be compared for equality using /// their bytewise representation -trait BytewiseEquality { } +trait BytewiseEquality: Eq + Copy { } macro_rules! impl_marker_for { ($traitname:ident, $($ty:ty)*) => { |
