3
3
use super :: { from_raw_parts, memchr} ;
4
4
use crate :: ascii;
5
5
use crate :: cmp:: { self , BytewiseEq , Ordering } ;
6
+ use crate :: convert:: Infallible ;
6
7
use crate :: intrinsics:: compare_bytes;
8
+ use crate :: marker:: Destruct ;
7
9
use crate :: num:: NonZero ;
8
10
use crate :: ops:: ControlFlow ;
9
11
@@ -23,18 +25,20 @@ where
23
25
}
24
26
25
27
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
26
- impl < T : Eq > Eq for [ T ] { }
28
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
29
+ impl < T : [ const ] Eq > const Eq for [ T ] { }
27
30
28
31
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
29
32
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
30
- impl < T : Ord > Ord for [ T ] {
33
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
34
+ impl <T : [ const ] Ord > const Ord for [ T ] {
31
35
fn cmp ( & self , other : & [ T ] ) -> Ordering {
32
36
SliceOrd :: compare ( self , other)
33
37
}
34
38
}
35
39
36
40
#[ inline]
37
- fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
41
+ const fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
38
42
// SAFETY: This will only compile if `bool` and `ControlFlow<bool>` have the same
39
43
// size (which isn't guaranteed but this is libcore). Because they have the same
40
44
// size, it's a niched implementation, which in one byte means there can't be
@@ -46,7 +50,8 @@ fn as_underlying(x: ControlFlow<bool>) -> u8 {
46
50
47
51
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
48
52
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
49
- impl < T : PartialOrd > PartialOrd for [ T ] {
53
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
54
+ impl <T : [ const ] PartialOrd > const PartialOrd for [ T ] {
50
55
#[ inline ]
51
56
fn partial_cmp ( & self , other : & [ T ] ) -> Option < Ordering > {
52
57
SlicePartialOrd :: partial_compare ( self , other )
@@ -95,9 +100,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
95
100
96
101
#[ doc( hidden) ]
97
102
// intermediate trait for specialization of slice's PartialEq
98
- #[ const_trait]
99
103
#[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
100
- trait SlicePartialEq < B > {
104
+ const trait SlicePartialEq < B > {
101
105
fn equal ( & self , other : & [ B ] ) -> bool ;
102
106
103
107
fn not_equal ( & self , other : & [ B ] ) -> bool {
@@ -155,35 +159,50 @@ where
155
159
}
156
160
157
161
#[ doc( hidden) ]
162
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
158
163
// intermediate trait for specialization of slice's PartialOrd
159
- trait SlicePartialOrd : Sized {
164
+ const trait SlicePartialOrd : Sized {
160
165
fn partial_compare ( left : & [ Self ] , right : & [ Self ] ) -> Option < Ordering > ;
161
166
}
162
167
163
168
#[ doc ( hidden ) ]
169
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
164
170
// intermediate trait for specialization of slice's PartialOrd chaining methods
165
- trait SliceChain : Sized {
171
+ const trait SliceChain : Sized {
166
172
fn chaining_lt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
167
173
fn chaining_le ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
168
174
fn chaining_gt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
169
175
fn chaining_ge ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
170
176
}
171
177
172
- type AlwaysBreak < B > = ControlFlow < B , crate :: convert:: Infallible > ;
178
+ type AlwaysBreak < B > = ControlFlow < B , Infallible > ;
179
+
180
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
181
+ const fn elem_chain < B > ( a : & B , b : & B ) -> ControlFlow < Option < Ordering > >
182
+ where
183
+ B : [ const ] PartialOrd ,
184
+ {
185
+ match a. partial_cmp ( b ) {
186
+ Some ( Ordering :: Equal ) => ControlFlow :: Continue ( ( ) ) ,
187
+ non_eq => ControlFlow :: Break ( non_eq ) ,
188
+ }
189
+ }
190
+
191
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
192
+ const fn len_chain ( a : & usize , b : & usize ) -> ControlFlow < Option < Ordering > , Infallible > {
193
+ ControlFlow :: Break ( usize:: partial_cmp ( a , b ) )
194
+ }
173
195
174
- impl < A : PartialOrd > SlicePartialOrd for A {
196
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
197
+ impl <A : [ const ] PartialOrd > const SlicePartialOrd for A {
175
198
default fn partial_compare ( left : & [ A ] , right : & [ A ] ) -> Option < Ordering > {
176
- let elem_chain = |a, b| match PartialOrd :: partial_cmp ( a, b) {
177
- Some ( Ordering :: Equal ) => ControlFlow :: Continue ( ( ) ) ,
178
- non_eq => ControlFlow :: Break ( non_eq) ,
179
- } ;
180
- let len_chain = |a : & _ , b : & _ | ControlFlow :: Break ( usize:: partial_cmp ( a, b) ) ;
181
199
let AlwaysBreak :: Break ( b ) = chaining_impl ( left , right , elem_chain , len_chain ) ;
182
200
b
183
201
}
184
202
}
185
203
186
- impl < A : PartialOrd > SliceChain for A {
204
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
205
+ impl<A : [ const ] PartialOrd > const SliceChain for A {
187
206
default fn chaining_lt( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > {
188
207
chaining_impl( left, right, PartialOrd :: __chaining_lt, usize:: __chaining_lt)
189
208
}
@@ -199,21 +218,28 @@ impl<A: PartialOrd> SliceChain for A {
199
218
}
200
219
201
220
#[ inline]
202
- fn chaining_impl < ' l , ' r , A : PartialOrd , B , C > (
221
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
222
+ const fn chaining_impl < ' l , ' r , A : PartialOrd , B , C , X , Y > (
203
223
left: & ' l [ A ] ,
204
224
right: & ' r [ A ] ,
205
- elem_chain : impl Fn ( & ' l A , & ' r A ) -> ControlFlow < B > ,
206
- len_chain : impl for < ' a > FnOnce ( & ' a usize , & ' a usize ) -> ControlFlow < B , C > ,
207
- ) -> ControlFlow < B , C > {
225
+ elem_chain: X ,
226
+ len_chain: Y ,
227
+ ) -> ControlFlow < B , C >
228
+ where
229
+ X : [ const ] Destruct + [ const ] Fn ( & ' l A , & ' r A ) -> ControlFlow < B > ,
230
+ Y : [ const ] Destruct + for < ' a > [ const ] FnOnce ( & ' a usize, & ' a usize) -> ControlFlow < B , C > ,
231
+ {
208
232
let l = cmp:: min( left. len( ) , right. len( ) ) ;
209
233
210
234
// Slice to the loop iteration range to enable bound check
211
235
// elimination in the compiler
212
236
let lhs = & left[ ..l] ;
213
237
let rhs = & right[ ..l] ;
214
238
215
- for i in 0 ..l {
239
+ let mut i = 0 ;
240
+ while i < l {
216
241
elem_chain ( & lhs[ i] , & rhs[ i] ) ?;
242
+ i += 1 ;
217
243
}
218
244
219
245
len_chain ( & left. len ( ) , & right. len ( ) )
@@ -232,46 +258,65 @@ where
232
258
}
233
259
*/
234
260
235
- impl < A : AlwaysApplicableOrd > SlicePartialOrd for A {
261
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
262
+ impl <A : [ const ] AlwaysApplicableOrd > const SlicePartialOrd for A {
236
263
fn partial_compare ( left : & [ A ] , right : & [ A ] ) -> Option < Ordering > {
237
264
Some ( SliceOrd :: compare ( left , right ) )
238
265
}
239
266
}
240
267
241
268
#[ rustc_specialization_trait ]
242
- trait AlwaysApplicableOrd : SliceOrd + Ord { }
269
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
270
+ const trait AlwaysApplicableOrd : [ const ] SliceOrd + [ const ] Ord { }
243
271
244
272
macro_rules! always_applicable_ord {
245
273
( $( [ $( $p: tt) * ] $t: ty, ) * ) => {
246
- $( impl <$( $p) * > AlwaysApplicableOrd for $t { } ) *
274
+ $(
275
+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
276
+ impl <$( $p) * > const AlwaysApplicableOrd for $t { }
277
+ ) *
247
278
}
248
279
}
249
280
250
281
always_applicable_ord! {
251
282
[ ] u8 , [ ] u16 , [ ] u32 , [ ] u64 , [ ] u128 , [ ] usize ,
252
283
[ ] i8 , [ ] i16 , [ ] i32 , [ ] i64 , [ ] i128 , [ ] isize ,
253
284
[ ] bool , [ ] char ,
254
- [ T : ?Sized ] * const T , [ T : ?Sized ] * mut T ,
255
- [ T : AlwaysApplicableOrd ] & T ,
256
- [ T : AlwaysApplicableOrd ] & mut T ,
257
- [ T : AlwaysApplicableOrd ] Option <T >,
285
+ [ T : [ const ] AlwaysApplicableOrd ] & T ,
286
+ [ T : [ const ] AlwaysApplicableOrd ] & mut T ,
287
+ [ T : [ const ] AlwaysApplicableOrd ] Option <T >,
258
288
}
259
289
290
+ impl <T : ?Sized > AlwaysApplicableOrd for * const T { }
291
+ impl <T : ?Sized > AlwaysApplicableOrd for * mut T { }
292
+
260
293
#[ doc( hidden) ]
261
294
// intermediate trait for specialization of slice's Ord
262
- trait SliceOrd : Sized {
295
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
296
+ const trait SliceOrd : Sized {
263
297
fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering ;
264
298
}
265
299
266
- impl < A : Ord > SliceOrd for A {
300
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
301
+ impl <A : [ const ] Ord > const SliceOrd for A {
267
302
default fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering {
268
- let elem_chain = |a, b| match Ord :: cmp ( a, b) {
269
- Ordering :: Equal => ControlFlow :: Continue ( ( ) ) ,
270
- non_eq => ControlFlow :: Break ( non_eq) ,
271
- } ;
272
- let len_chain = |a : & _ , b : & _ | ControlFlow :: Break ( usize:: cmp ( a, b) ) ;
273
- let AlwaysBreak :: Break ( b) = chaining_impl ( left, right, elem_chain, len_chain) ;
274
- b
303
+ let l = cmp:: min( left. len( ) , right. len( ) ) ;
304
+
305
+ // Slice to the loop iteration range to enable bound check
306
+ // elimination in the compiler
307
+ let lhs = & left[ ..l] ;
308
+ let rhs = & right[ ..l] ;
309
+
310
+ let mut i = 0 ;
311
+ while i < l {
312
+ match Ord :: cmp( & lhs[ i] , & rhs[ i] ) {
313
+ Ordering :: Equal => { }
314
+ non_eq => return non_eq,
315
+ }
316
+ i += 1 ;
317
+ }
318
+
319
+ usize :: cmp( & left. len( ) , & right. len( ) )
275
320
}
276
321
}
277
322
@@ -283,17 +328,19 @@ impl<A: Ord> SliceOrd for A {
283
328
/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
284
329
/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
285
330
#[ rustc_specialization_trait]
286
- unsafe trait UnsignedBytewiseOrd : Ord { }
331
+ #[ const_trait]
332
+ unsafe trait UnsignedBytewiseOrd : [ const ] Ord { }
287
333
288
- unsafe impl UnsignedBytewiseOrd for bool { }
289
- unsafe impl UnsignedBytewiseOrd for u8 { }
290
- unsafe impl UnsignedBytewiseOrd for NonZero < u8 > { }
291
- unsafe impl UnsignedBytewiseOrd for Option < NonZero < u8 > > { }
292
- unsafe impl UnsignedBytewiseOrd for ascii:: Char { }
334
+ unsafe impl const UnsignedBytewiseOrd for bool { }
335
+ unsafe impl const UnsignedBytewiseOrd for u8 { }
336
+ unsafe impl const UnsignedBytewiseOrd for NonZero <u8 > { }
337
+ unsafe impl const UnsignedBytewiseOrd for Option <NonZero <u8 >> { }
338
+ unsafe impl const UnsignedBytewiseOrd for ascii:: Char { }
293
339
294
340
// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so
295
341
// use it if the requirements for `UnsignedBytewiseOrd` are fulfilled.
296
- impl < A : Ord + UnsignedBytewiseOrd > SliceOrd for A {
342
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
343
+ impl <A : [ const ] Ord + [ const ] UnsignedBytewiseOrd > const SliceOrd for A {
297
344
#[ inline]
298
345
fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering {
299
346
// Since the length of a slice is always less than or equal to
@@ -318,7 +365,8 @@ impl<A: Ord + UnsignedBytewiseOrd> SliceOrd for A {
318
365
}
319
366
320
367
// Don't generate our own chaining loops for `memcmp`-able things either.
321
- impl < A : PartialOrd + UnsignedBytewiseOrd > SliceChain for A {
368
+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
369
+ impl <A : [ const ] PartialOrd + [ const ] UnsignedBytewiseOrd > const SliceChain for A {
322
370
#[ inline]
323
371
fn chaining_lt( left: & [ Self ] , right: & [ Self ] ) -> ControlFlow <bool > {
324
372
match SliceOrd :: compare( left, right) {
0 commit comments