|
| 1 | +use crate::cmp::BytewiseEq; |
1 | 2 | use crate::convert::TryInto; |
2 | | -use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; |
3 | | -use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; |
4 | 3 |
|
5 | 4 | #[stable(feature = "rust1", since = "1.0.0")] |
6 | 5 | impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N] |
@@ -144,74 +143,14 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T { |
144 | 143 | } |
145 | 144 | } |
146 | 145 |
|
147 | | -impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T { |
| 146 | +impl<T: BytewiseEq<U>, U, const N: usize> SpecArrayEq<U, N> for T { |
148 | 147 | fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { |
149 | | - // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. |
150 | | - unsafe { |
151 | | - let b = &*b.as_ptr().cast::<[T; N]>(); |
152 | | - crate::intrinsics::raw_eq(a, b) |
153 | | - } |
| 148 | + // SAFETY: Arrays are compared element-wise, and don't add any padding |
| 149 | + // between elements, so when the elements are `BytewiseEq`, we can |
| 150 | + // compare the entire array at once. |
| 151 | + unsafe { crate::intrinsics::raw_eq(a, crate::mem::transmute(b)) } |
154 | 152 | } |
155 | 153 | fn spec_ne(a: &[T; N], b: &[U; N]) -> bool { |
156 | 154 | !Self::spec_eq(a, b) |
157 | 155 | } |
158 | 156 | } |
159 | | - |
160 | | -/// `U` exists on here mostly because `min_specialization` didn't let me |
161 | | -/// repeat the `T` type parameter in the above specialization, so instead |
162 | | -/// the `T == U` constraint comes from the impls on this. |
163 | | -/// # Safety |
164 | | -/// - Neither `Self` nor `U` has any padding. |
165 | | -/// - `Self` and `U` have the same layout. |
166 | | -/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things) |
167 | | -#[rustc_specialization_trait] |
168 | | -unsafe trait IsRawEqComparable<U>: PartialEq<U> {} |
169 | | - |
170 | | -macro_rules! is_raw_eq_comparable { |
171 | | - ($($t:ty),+ $(,)?) => {$( |
172 | | - unsafe impl IsRawEqComparable<$t> for $t {} |
173 | | - )+}; |
174 | | -} |
175 | | - |
176 | | -// SAFETY: All the ordinary integer types have no padding, and are not pointers. |
177 | | -is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); |
178 | | - |
179 | | -// SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this |
180 | | -// is sound |
181 | | -is_raw_eq_comparable!(bool, char); |
182 | | - |
183 | | -// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers, |
184 | | -// and they compare like their underlying numeric type. |
185 | | -is_raw_eq_comparable!( |
186 | | - NonZeroU8, |
187 | | - NonZeroU16, |
188 | | - NonZeroU32, |
189 | | - NonZeroU64, |
190 | | - NonZeroU128, |
191 | | - NonZeroUsize, |
192 | | - NonZeroI8, |
193 | | - NonZeroI16, |
194 | | - NonZeroI32, |
195 | | - NonZeroI64, |
196 | | - NonZeroI128, |
197 | | - NonZeroIsize, |
198 | | -); |
199 | | - |
200 | | -// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus |
201 | | -// are also safe to equality-compare bitwise inside an `Option`. |
202 | | -// The way `PartialOrd` is defined for `Option` means that this wouldn't work |
203 | | -// for `<` or `>` on the signed types, but since we only do `==` it's fine. |
204 | | -is_raw_eq_comparable!( |
205 | | - Option<NonZeroU8>, |
206 | | - Option<NonZeroU16>, |
207 | | - Option<NonZeroU32>, |
208 | | - Option<NonZeroU64>, |
209 | | - Option<NonZeroU128>, |
210 | | - Option<NonZeroUsize>, |
211 | | - Option<NonZeroI8>, |
212 | | - Option<NonZeroI16>, |
213 | | - Option<NonZeroI32>, |
214 | | - Option<NonZeroI64>, |
215 | | - Option<NonZeroI128>, |
216 | | - Option<NonZeroIsize>, |
217 | | -); |
0 commit comments