diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-05-30 10:25:41 -0700 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-07-08 14:55:54 -0700 |
| commit | 2456495a260827217d3c612d6c577c2f165c61eb (patch) | |
| tree | e85ffd47a15f93a5b6f0a6324bb8b747659a2448 /library/core/src/array/equality.rs | |
| parent | d05eafae2fcc05bd64ab094a1352a5c16df3106e (diff) | |
| download | rust-2456495a260827217d3c612d6c577c2f165c61eb.tar.gz rust-2456495a260827217d3c612d6c577c2f165c61eb.zip | |
Stop generating `alloca`s+`memcmp` for simple array equality
Diffstat (limited to 'library/core/src/array/equality.rs')
| -rw-r--r-- | library/core/src/array/equality.rs | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index dcd78e7a245..6d66b9e2f27 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -5,11 +5,11 @@ where { #[inline] fn eq(&self, other: &[B; N]) -> bool { - self[..] == other[..] + SpecArrayEq::spec_eq(self, other) } #[inline] fn ne(&self, other: &[B; N]) -> bool { - self[..] != other[..] + SpecArrayEq::spec_ne(self, other) } } @@ -109,3 +109,52 @@ where #[stable(feature = "rust1", since = "1.0.0")] impl<T: Eq, const N: usize> Eq for [T; N] {} + +trait SpecArrayEq<Other, const N: usize>: Sized { + fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; + fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; +} + +impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T { + default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] == b[..] + } + default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool { + a[..] != b[..] + } +} + +impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { + #[cfg(bootstrap)] + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { + a[..] == b[..] + } + #[cfg(not(bootstrap))] + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { + // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. + unsafe { + let b = &*b.as_ptr().cast::<[T; N]>(); + crate::intrinsics::raw_eq(a, b) + } + } + fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { + !Self::spec_eq(a, b) + } +} + +/// `U` exists on here mostly because `min_specialization` didn't let me +/// repeat the `T` type parameter in the above specialization, so instead +/// the `T == U` constraint comes from the impls on this. +/// # Safety +/// - Neither `Self` nor `U` has any padding. +/// - `Self` and `U` have the same layout. +/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things) +#[rustc_specialization_trait] +unsafe trait IsRawEqComparable<U> {} + +macro_rules! is_raw_comparable { + ($($t:ty),+) => {$( + unsafe impl IsRawEqComparable<$t> for $t {} + )+}; +} +is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); |
