]> git.lizzy.rs Git - rust.git/blob - library/core/src/array/equality.rs
Replace `ConstFnMutClosure` with const closures
[rust.git] / library / core / src / array / equality.rs
1 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
5 #[stable(feature = "rust1", since = "1.0.0")]
6 impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
7 where
8     A: PartialEq<B>,
9 {
10     #[inline]
11     fn eq(&self, other: &[B; N]) -> bool {
12         SpecArrayEq::spec_eq(self, other)
13     }
14     #[inline]
15     fn ne(&self, other: &[B; N]) -> bool {
16         SpecArrayEq::spec_ne(self, other)
17     }
18 }
19
20 #[stable(feature = "rust1", since = "1.0.0")]
21 impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
22 where
23     A: PartialEq<B>,
24 {
25     #[inline]
26     fn eq(&self, other: &[B]) -> bool {
27         let b: Result<&[B; N], _> = other.try_into();
28         match b {
29             Ok(b) => *self == *b,
30             Err(_) => false,
31         }
32     }
33     #[inline]
34     fn ne(&self, other: &[B]) -> bool {
35         let b: Result<&[B; N], _> = other.try_into();
36         match b {
37             Ok(b) => *self != *b,
38             Err(_) => true,
39         }
40     }
41 }
42
43 #[stable(feature = "rust1", since = "1.0.0")]
44 impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
45 where
46     B: PartialEq<A>,
47 {
48     #[inline]
49     fn eq(&self, other: &[A; N]) -> bool {
50         let b: Result<&[B; N], _> = self.try_into();
51         match b {
52             Ok(b) => *b == *other,
53             Err(_) => false,
54         }
55     }
56     #[inline]
57     fn ne(&self, other: &[A; N]) -> bool {
58         let b: Result<&[B; N], _> = self.try_into();
59         match b {
60             Ok(b) => *b != *other,
61             Err(_) => true,
62         }
63     }
64 }
65
66 #[stable(feature = "rust1", since = "1.0.0")]
67 impl<A, B, const N: usize> PartialEq<&[B]> for [A; N]
68 where
69     A: PartialEq<B>,
70 {
71     #[inline]
72     fn eq(&self, other: &&[B]) -> bool {
73         *self == **other
74     }
75     #[inline]
76     fn ne(&self, other: &&[B]) -> bool {
77         *self != **other
78     }
79 }
80
81 #[stable(feature = "rust1", since = "1.0.0")]
82 impl<A, B, const N: usize> PartialEq<[A; N]> for &[B]
83 where
84     B: PartialEq<A>,
85 {
86     #[inline]
87     fn eq(&self, other: &[A; N]) -> bool {
88         **self == *other
89     }
90     #[inline]
91     fn ne(&self, other: &[A; N]) -> bool {
92         **self != *other
93     }
94 }
95
96 #[stable(feature = "rust1", since = "1.0.0")]
97 impl<A, B, const N: usize> PartialEq<&mut [B]> for [A; N]
98 where
99     A: PartialEq<B>,
100 {
101     #[inline]
102     fn eq(&self, other: &&mut [B]) -> bool {
103         *self == **other
104     }
105     #[inline]
106     fn ne(&self, other: &&mut [B]) -> bool {
107         *self != **other
108     }
109 }
110
111 #[stable(feature = "rust1", since = "1.0.0")]
112 impl<A, B, const N: usize> PartialEq<[A; N]> for &mut [B]
113 where
114     B: PartialEq<A>,
115 {
116     #[inline]
117     fn eq(&self, other: &[A; N]) -> bool {
118         **self == *other
119     }
120     #[inline]
121     fn ne(&self, other: &[A; N]) -> bool {
122         **self != *other
123     }
124 }
125
126 // NOTE: some less important impls are omitted to reduce code bloat
127 // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
128 // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
129
130 #[stable(feature = "rust1", since = "1.0.0")]
131 impl<T: Eq, const N: usize> Eq for [T; N] {}
132
133 trait SpecArrayEq<Other, const N: usize>: Sized {
134     fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool;
135     fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool;
136 }
137
138 impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
139     default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool {
140         a[..] == b[..]
141     }
142     default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool {
143         a[..] != b[..]
144     }
145 }
146
147 impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T {
148     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         }
154     }
155     fn spec_ne(a: &[T; N], b: &[U; N]) -> bool {
156         !Self::spec_eq(a, b)
157     }
158 }
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 );