diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-12-10 17:30:39 -0800 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2021-12-10 17:30:39 -0800 |
| commit | 24affba02e1db9fdfe446e68a74a0ba98acbdd71 (patch) | |
| tree | e76ba7acd611743b5d901c2dc63f645a326f9e8c /library/core/src/array/equality.rs | |
| parent | f0448f44bcda55fd9eb71da82495ef648eedb4e4 (diff) | |
| download | rust-24affba02e1db9fdfe446e68a74a0ba98acbdd71.tar.gz rust-24affba02e1db9fdfe446e68a74a0ba98acbdd71.zip | |
Allow `memcmp` for more array comparisons
This way comparing `[NonZeroU8; 8]` is just as fast as comparing `[u8; 8]`.
Diffstat (limited to 'library/core/src/array/equality.rs')
| -rw-r--r-- | library/core/src/array/equality.rs | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index a882d18b151..25e056501be 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -1,3 +1,6 @@ +use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; +use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; + #[stable(feature = "rust1", since = "1.0.0")] impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N] where @@ -124,7 +127,7 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T { } } -impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { +impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. unsafe { @@ -145,11 +148,52 @@ impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N /// - `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> {} +unsafe trait IsRawEqComparable<U>: PartialEq<U> {} -macro_rules! is_raw_comparable { - ($($t:ty),+) => {$( +macro_rules! is_raw_eq_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); + +// SAFETY: All the ordinary integer types allow all bit patterns as distinct values +is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// SAFETY: bool and char have *niches*, but no *padding*, so this is sound +is_raw_eq_comparable!(bool, char); + +// SAFETY: Similarly, the non-zero types have a niche, but no undef, +// and they compare like their underlying numeric type. +is_raw_eq_comparable!( + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize, + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, +); + +// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus +// are also safe to equality-compare bitwise inside an `Option`. +// The way `PartialOrd` is defined for `Option` means that this wouldn't work +// for `<` or `>` on the signed types, but since we only do `==` it's fine. +is_raw_eq_comparable!( + Option<NonZeroU8>, + Option<NonZeroU16>, + Option<NonZeroU32>, + Option<NonZeroU64>, + Option<NonZeroU128>, + Option<NonZeroUsize>, + Option<NonZeroI8>, + Option<NonZeroI16>, + Option<NonZeroI32>, + Option<NonZeroI64>, + Option<NonZeroI128>, + Option<NonZeroIsize>, +); |
