Skip to content

Commit f6dfc86

Browse files
committed
constify comparison traits on slices
1 parent 965a2b0 commit f6dfc86

File tree

1 file changed

+71
-35
lines changed

1 file changed

+71
-35
lines changed

library/core/src/slice/cmp.rs

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
use super::{from_raw_parts, memchr};
44
use crate::ascii;
55
use crate::cmp::{self, BytewiseEq, Ordering};
6+
use crate::convert::Infallible;
67
use crate::intrinsics::compare_bytes;
8+
use crate::marker::Destruct;
79
use crate::num::NonZero;
810
use crate::ops::ControlFlow;
911

@@ -28,7 +30,8 @@ impl<T: [const] Eq> const Eq for [T] {}
2830

2931
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
3032
#[stable(feature = "rust1", since = "1.0.0")]
31-
impl<T: Ord> Ord for [T] {
33+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
34+
impl<T: [const] Ord> const Ord for [T] {
3235
fn cmp(&self, other: &[T]) -> Ordering {
3336
SliceOrd::compare(self, other)
3437
}
@@ -47,7 +50,8 @@ const fn as_underlying(x: ControlFlow<bool>) -> u8 {
4750

4851
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
4952
#[stable(feature = "rust1", since = "1.0.0")]
50-
impl<T: PartialOrd> PartialOrd for [T] {
53+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
54+
impl<T: [const] PartialOrd> const PartialOrd for [T] {
5155
#[inline]
5256
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
5357
SlicePartialOrd::partial_compare(self, other)
@@ -155,39 +159,50 @@ where
155159
}
156160

157161
#[doc(hidden)]
158-
#[const_trait]
159162
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
160163
// intermediate trait for specialization of slice's PartialOrd
161-
trait SlicePartialOrd: Sized {
164+
const trait SlicePartialOrd: Sized {
162165
fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>;
163166
}
164167

165168
#[doc(hidden)]
166-
#[const_trait]
167169
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
168170
// intermediate trait for specialization of slice's PartialOrd chaining methods
169-
trait SliceChain: Sized {
171+
const trait SliceChain: Sized {
170172
fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
171173
fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
172174
fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
173175
fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
174176
}
175177

176-
type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
178+
type AlwaysBreak<B> = ControlFlow<B, Infallible>;
177179

178-
impl<A: PartialOrd> SlicePartialOrd for A {
180+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
181+
impl<A: [const] PartialOrd> const SlicePartialOrd for A {
179182
default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
180-
let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) {
181-
Some(Ordering::Equal) => ControlFlow::Continue(()),
182-
non_eq => ControlFlow::Break(non_eq),
183-
};
184-
let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
183+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
184+
const fn elem_chain<B>(a: &B, b: &B) -> ControlFlow<Option<Ordering>>
185+
where
186+
B: [const] PartialOrd,
187+
{
188+
match a.partial_cmp(b) {
189+
Some(Ordering::Equal) => ControlFlow::Continue(()),
190+
non_eq => ControlFlow::Break(non_eq),
191+
}
192+
}
193+
194+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
195+
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Option<Ordering>, Infallible> {
196+
ControlFlow::Break(usize::partial_cmp(a, b))
197+
}
198+
185199
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
186200
b
187201
}
188202
}
189203

190-
impl<A: PartialOrd> SliceChain for A {
204+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
205+
impl<A: [const] PartialOrd> const SliceChain for A {
191206
default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
192207
chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
193208
}
@@ -203,21 +218,28 @@ impl<A: PartialOrd> SliceChain for A {
203218
}
204219

205220
#[inline]
206-
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, E, L>(
207223
left: &'l [A],
208224
right: &'r [A],
209-
elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow<B>,
210-
len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
211-
) -> ControlFlow<B, C> {
225+
elem_chain: E,
226+
len_chain: L,
227+
) -> ControlFlow<B, C>
228+
where
229+
E: [const] Destruct + [const] Fn(&'l A, &'r A) -> ControlFlow<B>,
230+
L: [const] Destruct + for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
231+
{
212232
let l = cmp::min(left.len(), right.len());
213233

214234
// Slice to the loop iteration range to enable bound check
215235
// elimination in the compiler
216236
let lhs = &left[..l];
217237
let rhs = &right[..l];
218238

219-
for i in 0..l {
239+
let mut i = 0;
240+
while i < l {
220241
elem_chain(&lhs[i], &rhs[i])?;
242+
i += 1;
221243
}
222244

223245
len_chain(&left.len(), &right.len())
@@ -244,41 +266,56 @@ impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
244266
}
245267

246268
#[rustc_specialization_trait]
247-
#[const_trait]
248269
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
249-
trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
270+
const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
250271

251272
macro_rules! always_applicable_ord {
252273
($([$($p:tt)*] $t:ty,)*) => {
253-
$(impl<$($p)*> AlwaysApplicableOrd for $t {})*
274+
$(
275+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
276+
impl<$($p)*> const AlwaysApplicableOrd for $t {}
277+
)*
254278
}
255279
}
256280

257281
always_applicable_ord! {
258282
[] u8, [] u16, [] u32, [] u64, [] u128, [] usize,
259283
[] i8, [] i16, [] i32, [] i64, [] i128, [] isize,
260284
[] bool, [] char,
261-
[T: ?Sized] *const T, [T: ?Sized] *mut T,
262-
[T: AlwaysApplicableOrd] &T,
263-
[T: AlwaysApplicableOrd] &mut T,
264-
[T: AlwaysApplicableOrd] Option<T>,
285+
[T: [const] AlwaysApplicableOrd] &T,
286+
[T: [const] AlwaysApplicableOrd] &mut T,
287+
[T: [const] AlwaysApplicableOrd] Option<T>,
265288
}
266289

290+
impl<T: ?Sized> AlwaysApplicableOrd for *const T {}
291+
impl<T: ?Sized> AlwaysApplicableOrd for *mut T {}
292+
267293
#[doc(hidden)]
268-
#[const_trait]
269294
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
270295
// intermediate trait for specialization of slice's Ord
271-
trait SliceOrd: Sized {
296+
const trait SliceOrd: Sized {
272297
fn compare(left: &[Self], right: &[Self]) -> Ordering;
273298
}
274299

275-
impl<A: Ord> SliceOrd for A {
300+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
301+
impl<A: [const] Ord> const SliceOrd for A {
276302
default fn compare(left: &[Self], right: &[Self]) -> Ordering {
277-
let elem_chain = |a, b| match Ord::cmp(a, b) {
278-
Ordering::Equal => ControlFlow::Continue(()),
279-
non_eq => ControlFlow::Break(non_eq),
280-
};
281-
let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
303+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
304+
const fn elem_chain<B>(a: &B, b: &B) -> ControlFlow<Ordering>
305+
where
306+
B: [const] Ord,
307+
{
308+
match a.cmp(b) {
309+
Ordering::Equal => ControlFlow::Continue(()),
310+
non_eq => ControlFlow::Break(non_eq),
311+
}
312+
}
313+
314+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
315+
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Ordering, Infallible> {
316+
ControlFlow::Break(usize::cmp(a, b))
317+
}
318+
282319
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
283320
b
284321
}
@@ -334,7 +371,6 @@ impl<A: [const] Ord + [const] UnsignedBytewiseOrd> const SliceOrd for A {
334371
}
335372

336373
// Don't generate our own chaining loops for `memcmp`-able things either.
337-
338374
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
339375
impl<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> const SliceChain for A {
340376
#[inline]

0 commit comments

Comments
 (0)