From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- library/core/src/array/equality.rs | 216 +++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 library/core/src/array/equality.rs (limited to 'library/core/src/array/equality.rs') diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs new file mode 100644 index 000000000..33f7f494e --- /dev/null +++ b/library/core/src/array/equality.rs @@ -0,0 +1,216 @@ +use crate::convert::TryInto; +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 PartialEq<[B; N]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &[B; N]) -> bool { + SpecArrayEq::spec_eq(self, other) + } + #[inline] + fn ne(&self, other: &[B; N]) -> bool { + SpecArrayEq::spec_ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &[B]) -> bool { + let b: Result<&[B; N], _> = other.try_into(); + match b { + Ok(b) => *self == *b, + Err(_) => false, + } + } + #[inline] + fn ne(&self, other: &[B]) -> bool { + let b: Result<&[B; N], _> = other.try_into(); + match b { + Ok(b) => *self != *b, + Err(_) => true, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for [B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + let b: Result<&[B; N], _> = self.try_into(); + match b { + Ok(b) => *b == *other, + Err(_) => false, + } + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + let b: Result<&[B; N], _> = self.try_into(); + match b { + Ok(b) => *b != *other, + Err(_) => true, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&[B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &&[B]) -> bool { + *self == **other + } + #[inline] + fn ne(&self, other: &&[B]) -> bool { + *self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for &[B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + **self == *other + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + **self != *other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<&mut [B]> for [A; N] +where + A: PartialEq, +{ + #[inline] + fn eq(&self, other: &&mut [B]) -> bool { + *self == **other + } + #[inline] + fn ne(&self, other: &&mut [B]) -> bool { + *self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq<[A; N]> for &mut [B] +where + B: PartialEq, +{ + #[inline] + fn eq(&self, other: &[A; N]) -> bool { + **self == *other + } + #[inline] + fn ne(&self, other: &[A; N]) -> bool { + **self != *other + } +} + +// NOTE: some less important impls are omitted to reduce code bloat +// __impl_slice_eq2! { [A; $N], &'b [B; $N] } +// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T; N] {} + +trait SpecArrayEq: Sized { + fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; + fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; +} + +impl, Other, const N: usize> SpecArrayEq 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, U, const N: usize> SpecArrayEq for T { + 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` is byte-wise (this means no floats, among other things) +#[rustc_specialization_trait] +unsafe trait IsRawEqComparable: PartialEq {} + +macro_rules! is_raw_eq_comparable { + ($($t:ty),+ $(,)?) => {$( + unsafe impl IsRawEqComparable<$t> for $t {} + )+}; +} + +// 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, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, +); -- cgit v1.2.3