33use super :: { from_raw_parts, memchr} ;
44use crate :: ascii;
55use crate :: cmp:: { self , BytewiseEq , Ordering } ;
6+ use crate :: convert:: Infallible ;
67use crate :: intrinsics:: compare_bytes;
8+ use crate :: marker:: Destruct ;
79use crate :: num:: NonZero ;
810use crate :: ops:: ControlFlow ;
911
@@ -23,18 +25,20 @@ where
2325}
2426
2527#[ 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 ] { }
2730
2831/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
2932#[ 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 ] {
3135 fn cmp ( & self , other : & [ T ] ) -> Ordering {
3236 SliceOrd :: compare ( self , other)
3337 }
3438}
3539
3640#[ inline]
37- fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
41+ const fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
3842 // SAFETY: This will only compile if `bool` and `ControlFlow<bool>` have the same
3943 // size (which isn't guaranteed but this is libcore). Because they have the same
4044 // 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 {
4650
4751/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
4852#[ 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 ] {
5055 #[ inline ]
5156 fn partial_cmp ( & self , other : & [ T ] ) -> Option < Ordering > {
5257 SlicePartialOrd :: partial_compare ( self , other )
@@ -95,9 +100,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
95100
96101#[ doc( hidden) ]
97102// intermediate trait for specialization of slice's PartialEq
98- #[ const_trait]
99103#[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
100- trait SlicePartialEq < B > {
104+ const trait SlicePartialEq < B > {
101105 fn equal ( & self , other : & [ B ] ) -> bool ;
102106
103107 fn not_equal ( & self , other : & [ B ] ) -> bool {
@@ -155,35 +159,50 @@ where
155159}
156160
157161#[ doc( hidden) ]
162+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
158163// intermediate trait for specialization of slice's PartialOrd
159- trait SlicePartialOrd : Sized {
164+ const trait SlicePartialOrd : Sized {
160165 fn partial_compare ( left : & [ Self ] , right : & [ Self ] ) -> Option < Ordering > ;
161166}
162167
163168#[ doc ( hidden ) ]
169+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
164170// intermediate trait for specialization of slice's PartialOrd chaining methods
165- trait SliceChain : Sized {
171+ const trait SliceChain : Sized {
166172 fn chaining_lt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
167173 fn chaining_le ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
168174 fn chaining_gt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
169175 fn chaining_ge ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
170176}
171177
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+ }
173195
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 {
175198 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) ) ;
181199 let AlwaysBreak :: Break ( b ) = chaining_impl ( left , right , elem_chain , len_chain ) ;
182200 b
183201 }
184202}
185203
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 {
187206 default fn chaining_lt( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > {
188207 chaining_impl( left, right, PartialOrd :: __chaining_lt, usize:: __chaining_lt)
189208 }
@@ -199,21 +218,28 @@ impl<A: PartialOrd> SliceChain for A {
199218}
200219
201220#[ 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 > (
203223 left: & ' l [ A ] ,
204224 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+ {
208232 let l = cmp:: min( left. len( ) , right. len( ) ) ;
209233
210234 // Slice to the loop iteration range to enable bound check
211235 // elimination in the compiler
212236 let lhs = & left[ ..l] ;
213237 let rhs = & right[ ..l] ;
214238
215- for i in 0 ..l {
239+ let mut i = 0 ;
240+ while i < l {
216241 elem_chain ( & lhs[ i] , & rhs[ i] ) ?;
242+ i += 1 ;
217243 }
218244
219245 len_chain ( & left. len ( ) , & right. len ( ) )
@@ -232,46 +258,65 @@ where
232258}
233259*/
234260
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 {
236263 fn partial_compare ( left : & [ A ] , right : & [ A ] ) -> Option < Ordering > {
237264 Some ( SliceOrd :: compare ( left , right ) )
238265 }
239266}
240267
241268#[ 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 { }
243271
244272macro_rules! always_applicable_ord {
245273 ( $( [ $( $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+ ) *
247278 }
248279}
249280
250281always_applicable_ord! {
251282 [ ] u8 , [ ] u16 , [ ] u32 , [ ] u64 , [ ] u128 , [ ] usize ,
252283 [ ] i8 , [ ] i16 , [ ] i32 , [ ] i64 , [ ] i128 , [ ] isize ,
253284 [ ] 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 >,
258288}
259289
290+ impl <T : ?Sized > AlwaysApplicableOrd for * const T { }
291+ impl <T : ?Sized > AlwaysApplicableOrd for * mut T { }
292+
260293#[ doc( hidden) ]
261294// 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 {
263297 fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering ;
264298}
265299
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 {
267302 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( ) )
275320 }
276321}
277322
@@ -283,17 +328,19 @@ impl<A: Ord> SliceOrd for A {
283328/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
284329/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
285330 #[ rustc_specialization_trait]
286- unsafe trait UnsignedBytewiseOrd : Ord { }
331+ #[ const_trait]
332+ unsafe trait UnsignedBytewiseOrd : [ const ] Ord { }
287333
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 { }
293339
294340// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so
295341// 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 {
297344 #[ inline]
298345 fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering {
299346 // Since the length of a slice is always less than or equal to
@@ -318,7 +365,8 @@ impl<A: Ord + UnsignedBytewiseOrd> SliceOrd for A {
318365}
319366
320367// 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 {
322370 #[ inline]
323371 fn chaining_lt( left: & [ Self ] , right: & [ Self ] ) -> ControlFlow <bool > {
324372 match SliceOrd :: compare( left, right) {
0 commit comments