@@ -23,18 +23,20 @@ where
2323}
2424
2525#[ stable( feature = "rust1" , since = "1.0.0" ) ]
26- impl < T : Eq > Eq for [ T ] { }
26+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
27+ impl < T : [ const ] Eq > const Eq for [ T ] { }
2728
2829/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
2930#[ stable( feature = "rust1" , since = "1.0.0" ) ]
30- impl < T : Ord > Ord for [ T ] {
31+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
32+ impl <T : [ const ] Ord > const Ord for [ T ] {
3133 fn cmp ( & self , other : & [ T ] ) -> Ordering {
3234 SliceOrd :: compare ( self , other)
3335 }
3436}
3537
3638#[ inline]
37- fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
39+ const fn as_underlying ( x : ControlFlow < bool > ) -> u8 {
3840 // SAFETY: This will only compile if `bool` and `ControlFlow<bool>` have the same
3941 // size (which isn't guaranteed but this is libcore). Because they have the same
4042 // size, it's a niched implementation, which in one byte means there can't be
@@ -46,7 +48,8 @@ fn as_underlying(x: ControlFlow<bool>) -> u8 {
4648
4749/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
4850#[ stable( feature = "rust1" , since = "1.0.0" ) ]
49- impl < T : PartialOrd > PartialOrd for [ T ] {
51+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
52+ impl <T : [ const ] PartialOrd > const PartialOrd for [ T ] {
5053 #[ inline ]
5154 fn partial_cmp ( & self , other : & [ T ] ) -> Option < Ordering > {
5255 SlicePartialOrd :: partial_compare ( self , other )
@@ -95,9 +98,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
9598
9699#[ doc( hidden) ]
97100// intermediate trait for specialization of slice's PartialEq
98- #[ const_trait]
99101#[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
100- trait SlicePartialEq < B > {
102+ const trait SlicePartialEq < B > {
101103 fn equal ( & self , other : & [ B ] ) -> bool ;
102104
103105 fn not_equal ( & self , other : & [ B ] ) -> bool {
@@ -155,68 +157,123 @@ where
155157}
156158
157159#[ doc( hidden) ]
160+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
158161// intermediate trait for specialization of slice's PartialOrd
159- trait SlicePartialOrd : Sized {
162+ const trait SlicePartialOrd : Sized {
160163 fn partial_compare ( left : & [ Self ] , right : & [ Self ] ) -> Option < Ordering > ;
161164}
162165
163166#[ doc ( hidden ) ]
167+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
164168// intermediate trait for specialization of slice's PartialOrd chaining methods
165- trait SliceChain : Sized {
169+ const trait SliceChain : Sized {
166170 fn chaining_lt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
167171 fn chaining_le ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
168172 fn chaining_gt ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
169173 fn chaining_ge ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > ;
170174}
171175
172- type AlwaysBreak < B > = ControlFlow < B , crate :: convert:: Infallible > ;
173-
174- impl < A : PartialOrd > SlicePartialOrd for A {
176+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
177+ impl <A : [ const ] PartialOrd > const SlicePartialOrd for A {
175178 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- let AlwaysBreak :: Break ( b) = chaining_impl ( left, right, elem_chain, len_chain) ;
182- b
179+ let l = cmp:: min ( left . len( ) , right . len( ) ) ;
180+
181+ // Slice to the loop iteration range to enable bound check
182+ // elimination in the compiler
183+ let lhs = & left[ ..l] ;
184+ let rhs = & right[ ..l] ;
185+
186+ let mut i = 0 ;
187+ while i < l {
188+ match PartialOrd :: partial_cmp ( & lhs[ i] , & rhs[ i] ) {
189+ Some ( Ordering :: Equal ) => { }
190+ non_eq => return non_eq,
191+ }
192+ i += 1 ;
193+ }
194+
195+ usize:: partial_cmp ( & left. len ( ) , & right. len ( ) )
183196 }
184197}
185198
186- impl < A : PartialOrd > SliceChain for A {
199+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
200+ impl<A : [ const ] PartialOrd > const SliceChain for A {
187201 default fn chaining_lt( left : & [ Self ] , right: & [ Self ] ) -> ControlFlow < bool > {
188- chaining_impl ( left, right, PartialOrd :: __chaining_lt, usize:: __chaining_lt)
202+ let l = cmp:: min( left. len( ) , right. len( ) ) ;
203+
204+ // Slice to the loop iteration range to enable bound check
205+ // elimination in the compiler
206+ let lhs = & left[ ..l] ;
207+ let rhs = & right[ ..l] ;
208+
209+ let mut i = 0 ;
210+ while i < l {
211+ match PartialOrd :: __chaining_lt ( & lhs[ i] , & rhs[ i] ) {
212+ ControlFlow :: Continue ( ( ) ) => { }
213+ ControlFlow :: Break ( b) => return ControlFlow :: Break ( b) ,
214+ }
215+ i += 1 ;
216+ }
217+
218+ usize:: __chaining_lt ( & left. len ( ) , & right. len ( ) )
189219 }
190220 default fn chaining_le ( left : & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > {
191- chaining_impl ( left, right, PartialOrd :: __chaining_le, usize:: __chaining_le)
221+ let l = cmp:: min ( left. len ( ) , right. len ( ) ) ;
222+
223+ // Slice to the loop iteration range to enable bound check
224+ // elimination in the compiler
225+ let lhs = & left[ ..l] ;
226+ let rhs = & right[ ..l] ;
227+
228+ let mut i = 0 ;
229+ while i < l {
230+ match PartialOrd :: __chaining_le ( & lhs[ i] , & rhs[ i] ) {
231+ ControlFlow :: Continue ( ( ) ) => { }
232+ ControlFlow :: Break ( b) => return ControlFlow :: Break ( b) ,
233+ }
234+ i += 1 ;
235+ }
236+
237+ usize:: __chaining_le ( & left. len ( ) , & right. len ( ) )
192238 }
193239 default fn chaining_gt( left: & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > {
194- chaining_impl ( left, right, PartialOrd :: __chaining_gt, usize:: __chaining_gt)
240+ let l = cmp:: min ( left. len ( ) , right. len ( ) ) ;
241+
242+ // Slice to the loop iteration range to enable bound check
243+ // elimination in the compiler
244+ let lhs = & left[ ..l] ;
245+ let rhs = & right[ ..l] ;
246+
247+ let mut i = 0 ;
248+ while i < l {
249+ match PartialOrd :: __chaining_gt ( & lhs[ i] , & rhs[ i] ) {
250+ ControlFlow :: Continue ( ( ) ) => { }
251+ ControlFlow :: Break ( b) => return ControlFlow :: Break ( b) ,
252+ }
253+ i += 1 ;
254+ }
255+
256+ usize:: __chaining_gt ( & left. len ( ) , & right. len ( ) )
195257 }
196258 default fn chaining_ge( left: & [ Self ] , right : & [ Self ] ) -> ControlFlow < bool > {
197- chaining_impl ( left, right, PartialOrd :: __chaining_ge, usize:: __chaining_ge)
198- }
199- }
200-
201- #[ inline]
202- fn chaining_impl < ' l , ' r , A : PartialOrd , B , C > (
203- left : & ' l [ A ] ,
204- 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 > {
208- let l = cmp:: min ( left. len ( ) , right. len ( ) ) ;
209-
210- // Slice to the loop iteration range to enable bound check
211- // elimination in the compiler
212- let lhs = & left[ ..l] ;
213- let rhs = & right[ ..l] ;
259+ let l = cmp:: min ( left. len ( ) , right. len ( ) ) ;
260+
261+ // Slice to the loop iteration range to enable bound check
262+ // elimination in the compiler
263+ let lhs = & left[ ..l] ;
264+ let rhs = & right[ ..l] ;
265+
266+ let mut i = 0 ;
267+ while i < l {
268+ match PartialOrd :: __chaining_ge ( & lhs[ i] , & rhs[ i] ) {
269+ ControlFlow :: Continue ( ( ) ) => { }
270+ ControlFlow :: Break ( b) => return ControlFlow :: Break ( b) ,
271+ }
272+ i += 1 ;
273+ }
214274
215- for i in 0 ..l {
216- elem_chain ( & lhs[ i] , & rhs[ i] ) ?;
275+ usize:: __chaining_ge ( & left. len ( ) , & right. len ( ) )
217276 }
218-
219- len_chain ( & left. len ( ) , & right. len ( ) )
220277}
221278
222279// This is the impl that we would like to have. Unfortunately it's not sound.
@@ -232,46 +289,65 @@ where
232289}
233290*/
234291
235- impl < A : AlwaysApplicableOrd > SlicePartialOrd for A {
292+ #[ rustc_const_unstable( feature = "const_cmp", issue = "143800 ") ]
293+ impl <A : [ const ] AlwaysApplicableOrd > const SlicePartialOrd for A {
236294 fn partial_compare ( left : & [ A ] , right : & [ A ] ) -> Option < Ordering > {
237295 Some ( SliceOrd :: compare ( left , right ) )
238296 }
239297}
240298
241299#[ rustc_specialization_trait ]
242- trait AlwaysApplicableOrd : SliceOrd + Ord { }
300+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
301+ const trait AlwaysApplicableOrd : [ const ] SliceOrd + [ const ] Ord { }
243302
244303macro_rules! always_applicable_ord {
245304 ( $( [ $( $p: tt) * ] $t: ty, ) * ) => {
246- $( impl <$( $p) * > AlwaysApplicableOrd for $t { } ) *
305+ $(
306+ #[ rustc_const_unstable ( feature = "const_cmp" , issue = "143800" ) ]
307+ impl <$( $p) * > const AlwaysApplicableOrd for $t { }
308+ ) *
247309 }
248310}
249311
250312always_applicable_ord! {
251313 [ ] u8 , [ ] u16 , [ ] u32 , [ ] u64 , [ ] u128 , [ ] usize ,
252314 [ ] i8 , [ ] i16 , [ ] i32 , [ ] i64 , [ ] i128 , [ ] isize ,
253315 [ ] 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 >,
316+ [ T : [ const ] AlwaysApplicableOrd ] & T ,
317+ [ T : [ const ] AlwaysApplicableOrd ] & mut T ,
318+ [ T : [ const ] AlwaysApplicableOrd ] Option <T >,
258319}
259320
321+ impl <T : ?Sized > AlwaysApplicableOrd for * const T { }
322+ impl <T : ?Sized > AlwaysApplicableOrd for * mut T { }
323+
260324#[ doc( hidden) ]
261325// intermediate trait for specialization of slice's Ord
262- trait SliceOrd : Sized {
326+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
327+ const trait SliceOrd : Sized {
263328 fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering ;
264329}
265330
266- impl < A : Ord > SliceOrd for A {
331+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
332+ impl <A : [ const ] Ord > const SliceOrd for A {
267333 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
334+ let l = cmp:: min( left. len( ) , right. len( ) ) ;
335+
336+ // Slice to the loop iteration range to enable bound check
337+ // elimination in the compiler
338+ let lhs = & left[ ..l] ;
339+ let rhs = & right[ ..l] ;
340+
341+ let mut i = 0 ;
342+ while i < l {
343+ match Ord :: cmp( & lhs[ i] , & rhs[ i] ) {
344+ Ordering :: Equal => { }
345+ non_eq => return non_eq,
346+ }
347+ i += 1 ;
348+ }
349+
350+ usize :: cmp( & left. len( ) , & right. len( ) )
275351 }
276352}
277353
@@ -283,17 +359,19 @@ impl<A: Ord> SliceOrd for A {
283359/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
284360/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
285361 #[ rustc_specialization_trait]
286- unsafe trait UnsignedBytewiseOrd : Ord { }
362+ #[ const_trait]
363+ unsafe trait UnsignedBytewiseOrd : [ const ] Ord { }
287364
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 { }
365+ unsafe impl const UnsignedBytewiseOrd for bool { }
366+ unsafe impl const UnsignedBytewiseOrd for u8 { }
367+ unsafe impl const UnsignedBytewiseOrd for NonZero <u8 > { }
368+ unsafe impl const UnsignedBytewiseOrd for Option <NonZero <u8 >> { }
369+ unsafe impl const UnsignedBytewiseOrd for ascii:: Char { }
293370
294371// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so
295372// use it if the requirements for `UnsignedBytewiseOrd` are fulfilled.
296- impl < A : Ord + UnsignedBytewiseOrd > SliceOrd for A {
373+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
374+ impl <A : [ const ] Ord + [ const ] UnsignedBytewiseOrd > const SliceOrd for A {
297375 #[ inline]
298376 fn compare( left: & [ Self ] , right: & [ Self ] ) -> Ordering {
299377 // Since the length of a slice is always less than or equal to
@@ -318,7 +396,8 @@ impl<A: Ord + UnsignedBytewiseOrd> SliceOrd for A {
318396}
319397
320398// Don't generate our own chaining loops for `memcmp`-able things either.
321- impl < A : PartialOrd + UnsignedBytewiseOrd > SliceChain for A {
399+ #[ rustc_const_unstable( feature = "const_cmp" , issue = "143800" ) ]
400+ impl <A : [ const ] PartialOrd + [ const ] UnsignedBytewiseOrd > const SliceChain for A {
322401 #[ inline]
323402 fn chaining_lt( left: & [ Self ] , right: & [ Self ] ) -> ControlFlow <bool > {
324403 match SliceOrd :: compare( left, right) {
0 commit comments