1+ use crate :: num:: { NonZeroI128 , NonZeroI16 , NonZeroI32 , NonZeroI64 , NonZeroI8 , NonZeroIsize } ;
2+ use crate :: num:: { NonZeroU128 , NonZeroU16 , NonZeroU32 , NonZeroU64 , NonZeroU8 , NonZeroUsize } ;
3+
14#[ stable( feature = "rust1" , since = "1.0.0" ) ]
25impl < A , B , const N : usize > PartialEq < [ B ; N ] > for [ A ; N ]
36where
@@ -124,7 +127,7 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
124127 }
125128}
126129
127- impl < T : PartialEq < U > + IsRawEqComparable < U > , U , const N : usize > SpecArrayEq < U , N > for T {
130+ impl < T : IsRawEqComparable < U > , U , const N : usize > SpecArrayEq < U , N > for T {
128131 fn spec_eq ( a : & [ T ; N ] , b : & [ U ; N ] ) -> bool {
129132 // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`.
130133 unsafe {
@@ -145,11 +148,52 @@ impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N
145148/// - `Self` and `U` have the same layout.
146149/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things)
147150#[ rustc_specialization_trait]
148- unsafe trait IsRawEqComparable < U > { }
151+ unsafe trait IsRawEqComparable < U > : PartialEq < U > { }
149152
150- macro_rules! is_raw_comparable {
151- ( $( $t: ty) ,+) => { $(
153+ macro_rules! is_raw_eq_comparable {
154+ ( $( $t: ty) ,+ $ ( , ) ? ) => { $(
152155 unsafe impl IsRawEqComparable <$t> for $t { }
153156 ) +} ;
154157}
155- is_raw_comparable ! ( bool , char , u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ) ;
158+
159+ // SAFETY: All the ordinary integer types allow all bit patterns as distinct values
160+ is_raw_eq_comparable ! ( u8 , u16 , u32 , u64 , u128 , usize , i8 , i16 , i32 , i64 , i128 , isize ) ;
161+
162+ // SAFETY: bool and char have *niches*, but no *padding*, so this is sound
163+ is_raw_eq_comparable ! ( bool , char ) ;
164+
165+ // SAFETY: Similarly, the non-zero types have a niche, but no undef,
166+ // and they compare like their underlying numeric type.
167+ is_raw_eq_comparable ! (
168+ NonZeroU8 ,
169+ NonZeroU16 ,
170+ NonZeroU32 ,
171+ NonZeroU64 ,
172+ NonZeroU128 ,
173+ NonZeroUsize ,
174+ NonZeroI8 ,
175+ NonZeroI16 ,
176+ NonZeroI32 ,
177+ NonZeroI64 ,
178+ NonZeroI128 ,
179+ NonZeroIsize ,
180+ ) ;
181+
182+ // SAFETY: The NonZero types have the "null" optimization guaranteed, and thus
183+ // are also safe to equality-compare bitwise inside an `Option`.
184+ // The way `PartialOrd` is defined for `Option` means that this wouldn't work
185+ // for `<` or `>` on the signed types, but since we only do `==` it's fine.
186+ is_raw_eq_comparable ! (
187+ Option <NonZeroU8 >,
188+ Option <NonZeroU16 >,
189+ Option <NonZeroU32 >,
190+ Option <NonZeroU64 >,
191+ Option <NonZeroU128 >,
192+ Option <NonZeroUsize >,
193+ Option <NonZeroI8 >,
194+ Option <NonZeroI16 >,
195+ Option <NonZeroI32 >,
196+ Option <NonZeroI64 >,
197+ Option <NonZeroI128 >,
198+ Option <NonZeroIsize >,
199+ ) ;
0 commit comments