|
5 | 5 | {
|
6 | 6 | #[inline]
|
7 | 7 | fn eq(&self, other: &[B; N]) -> bool {
|
8 |
| - self[..] == other[..] |
| 8 | + SpecArrayEq::spec_eq(self, other) |
9 | 9 | }
|
10 | 10 | #[inline]
|
11 | 11 | fn ne(&self, other: &[B; N]) -> bool {
|
12 |
| - self[..] != other[..] |
| 12 | + SpecArrayEq::spec_ne(self, other) |
13 | 13 | }
|
14 | 14 | }
|
15 | 15 |
|
@@ -109,3 +109,52 @@ where
|
109 | 109 |
|
110 | 110 | #[stable(feature = "rust1", since = "1.0.0")]
|
111 | 111 | impl<T: Eq, const N: usize> Eq for [T; N] {}
|
| 112 | + |
| 113 | +trait SpecArrayEq<Other, const N: usize>: Sized { |
| 114 | + fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; |
| 115 | + fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; |
| 116 | +} |
| 117 | + |
| 118 | +impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T { |
| 119 | + default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool { |
| 120 | + a[..] == b[..] |
| 121 | + } |
| 122 | + default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool { |
| 123 | + a[..] != b[..] |
| 124 | + } |
| 125 | +} |
| 126 | + |
| 127 | +impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { |
| 128 | + #[cfg(bootstrap)] |
| 129 | + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { |
| 130 | + a[..] == b[..] |
| 131 | + } |
| 132 | + #[cfg(not(bootstrap))] |
| 133 | + fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { |
| 134 | + // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. |
| 135 | + unsafe { |
| 136 | + let b = &*b.as_ptr().cast::<[T; N]>(); |
| 137 | + crate::intrinsics::raw_eq(a, b) |
| 138 | + } |
| 139 | + } |
| 140 | + fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { |
| 141 | + !Self::spec_eq(a, b) |
| 142 | + } |
| 143 | +} |
| 144 | + |
| 145 | +/// `U` exists on here mostly because `min_specialization` didn't let me |
| 146 | +/// repeat the `T` type parameter in the above specialization, so instead |
| 147 | +/// the `T == U` constraint comes from the impls on this. |
| 148 | +/// # Safety |
| 149 | +/// - Neither `Self` nor `U` has any padding. |
| 150 | +/// - `Self` and `U` have the same layout. |
| 151 | +/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things) |
| 152 | +#[rustc_specialization_trait] |
| 153 | +unsafe trait IsRawEqComparable<U> {} |
| 154 | + |
| 155 | +macro_rules! is_raw_comparable { |
| 156 | + ($($t:ty),+) => {$( |
| 157 | + unsafe impl IsRawEqComparable<$t> for $t {} |
| 158 | + )+}; |
| 159 | +} |
| 160 | +is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); |
0 commit comments