Skip to content

Commit 7613af6

Browse files
authored
Rollup merge of rust-lang#147790 - npmccallum:slices, r=oli-obk
constify comparison traits on slices r? oli-obk Tracking issue rust-lang#143800
2 parents 85ca589 + 4b1d118 commit 7613af6

File tree

5 files changed

+110
-52
lines changed

5 files changed

+110
-52
lines changed

library/core/src/bstr/traits.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,35 @@ use crate::slice::SliceIndex;
66
use crate::{hash, ops, range};
77

88
#[unstable(feature = "bstr", issue = "134915")]
9-
impl Ord for ByteStr {
9+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
10+
impl const Ord for ByteStr {
1011
#[inline]
1112
fn cmp(&self, other: &ByteStr) -> Ordering {
1213
Ord::cmp(&self.0, &other.0)
1314
}
1415
}
1516

1617
#[unstable(feature = "bstr", issue = "134915")]
17-
impl PartialOrd for ByteStr {
18+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
19+
impl const PartialOrd for ByteStr {
1820
#[inline]
1921
fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
2022
PartialOrd::partial_cmp(&self.0, &other.0)
2123
}
2224
}
2325

2426
#[unstable(feature = "bstr", issue = "134915")]
25-
impl PartialEq<ByteStr> for ByteStr {
27+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
28+
impl const PartialEq<ByteStr> for ByteStr {
2629
#[inline]
2730
fn eq(&self, other: &ByteStr) -> bool {
2831
&self.0 == &other.0
2932
}
3033
}
3134

3235
#[unstable(feature = "bstr", issue = "134915")]
33-
impl Eq for ByteStr {}
36+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
37+
impl const Eq for ByteStr {}
3438

3539
#[unstable(feature = "bstr", issue = "134915")]
3640
impl hash::Hash for ByteStr {

library/core/src/ffi/c_str.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ use crate::{fmt, ops, slice, str};
8888
/// ```
8989
///
9090
/// [str]: prim@str "str"
91-
#[derive(PartialEq, Eq, Hash)]
91+
#[derive(Hash)]
92+
#[derive_const(PartialEq, Eq)]
9293
#[stable(feature = "core_c_str", since = "1.64.0")]
9394
#[rustc_diagnostic_item = "cstr_type"]
9495
#[rustc_has_incoherent_inherent_impls]
@@ -667,15 +668,17 @@ impl PartialEq<&Self> for CStr {
667668
// because `c_char` is `i8` (not `u8`) on some platforms.
668669
// That is why this is implemented manually and not derived.
669670
#[stable(feature = "rust1", since = "1.0.0")]
670-
impl PartialOrd for CStr {
671+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
672+
impl const PartialOrd for CStr {
671673
#[inline]
672674
fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
673675
self.to_bytes().partial_cmp(&other.to_bytes())
674676
}
675677
}
676678

677679
#[stable(feature = "rust1", since = "1.0.0")]
678-
impl Ord for CStr {
680+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
681+
impl const Ord for CStr {
679682
#[inline]
680683
fn cmp(&self, other: &CStr) -> Ordering {
681684
self.to_bytes().cmp(&other.to_bytes())

library/core/src/panic/location.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ pub struct Location<'a> {
4747
}
4848

4949
#[stable(feature = "panic_hooks", since = "1.10.0")]
50-
impl PartialEq for Location<'_> {
50+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
51+
impl const PartialEq for Location<'_> {
5152
fn eq(&self, other: &Self) -> bool {
5253
// Compare col / line first as they're cheaper to compare and more likely to differ,
5354
// while not impacting the result.
@@ -56,20 +57,29 @@ impl PartialEq for Location<'_> {
5657
}
5758

5859
#[stable(feature = "panic_hooks", since = "1.10.0")]
59-
impl Eq for Location<'_> {}
60+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
61+
impl const Eq for Location<'_> {}
6062

6163
#[stable(feature = "panic_hooks", since = "1.10.0")]
62-
impl Ord for Location<'_> {
64+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
65+
impl const Ord for Location<'_> {
6366
fn cmp(&self, other: &Self) -> Ordering {
64-
self.file()
65-
.cmp(other.file())
66-
.then_with(|| self.line.cmp(&other.line))
67-
.then_with(|| self.col.cmp(&other.col))
67+
// FIXME(const-hack): This uses match instead of `then_with` as a
68+
// workaround for the lack of const closures. Revert to using
69+
// `then_with` once const closures are available.
70+
match self.file().cmp(other.file()) {
71+
Ordering::Equal => match self.line.cmp(&other.line) {
72+
Ordering::Equal => self.col.cmp(&other.col),
73+
ordering => ordering,
74+
},
75+
ordering => ordering,
76+
}
6877
}
6978
}
7079

7180
#[stable(feature = "panic_hooks", since = "1.10.0")]
72-
impl PartialOrd for Location<'_> {
81+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
82+
impl const PartialOrd for Location<'_> {
7383
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
7484
Some(self.cmp(other))
7585
}

library/core/src/slice/cmp.rs

Lines changed: 74 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,31 @@ 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+
// FIXME(const-hack): This uses a `while` loop instead of `for` as a
240+
// workaround for the lack of const iterators. Revert to using `for` once
241+
// const iterators are available.
242+
let mut i = 0;
243+
while i < l {
220244
elem_chain(&lhs[i], &rhs[i])?;
245+
i += 1;
221246
}
222247

223248
len_chain(&left.len(), &right.len())
@@ -244,41 +269,56 @@ impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
244269
}
245270

246271
#[rustc_specialization_trait]
247-
#[const_trait]
248272
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
249-
trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
273+
const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
250274

251275
macro_rules! always_applicable_ord {
252276
($([$($p:tt)*] $t:ty,)*) => {
253-
$(impl<$($p)*> AlwaysApplicableOrd for $t {})*
277+
$(
278+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
279+
impl<$($p)*> const AlwaysApplicableOrd for $t {}
280+
)*
254281
}
255282
}
256283

257284
always_applicable_ord! {
258285
[] u8, [] u16, [] u32, [] u64, [] u128, [] usize,
259286
[] i8, [] i16, [] i32, [] i64, [] i128, [] isize,
260287
[] 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>,
288+
[T: [const] AlwaysApplicableOrd] &T,
289+
[T: [const] AlwaysApplicableOrd] &mut T,
290+
[T: [const] AlwaysApplicableOrd] Option<T>,
265291
}
266292

293+
impl<T: ?Sized> AlwaysApplicableOrd for *const T {}
294+
impl<T: ?Sized> AlwaysApplicableOrd for *mut T {}
295+
267296
#[doc(hidden)]
268-
#[const_trait]
269297
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
270298
// intermediate trait for specialization of slice's Ord
271-
trait SliceOrd: Sized {
299+
const trait SliceOrd: Sized {
272300
fn compare(left: &[Self], right: &[Self]) -> Ordering;
273301
}
274302

275-
impl<A: Ord> SliceOrd for A {
303+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
304+
impl<A: [const] Ord> const SliceOrd for A {
276305
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));
306+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
307+
const fn elem_chain<B>(a: &B, b: &B) -> ControlFlow<Ordering>
308+
where
309+
B: [const] Ord,
310+
{
311+
match a.cmp(b) {
312+
Ordering::Equal => ControlFlow::Continue(()),
313+
non_eq => ControlFlow::Break(non_eq),
314+
}
315+
}
316+
317+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
318+
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Ordering, Infallible> {
319+
ControlFlow::Break(usize::cmp(a, b))
320+
}
321+
282322
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
283323
b
284324
}
@@ -334,7 +374,6 @@ impl<A: [const] Ord + [const] UnsignedBytewiseOrd> const SliceOrd for A {
334374
}
335375

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

library/core/src/str/traits.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::{ops, ptr, range};
1515
/// culturally-accepted standards requires locale-specific data that is outside the scope of
1616
/// the `str` type.
1717
#[stable(feature = "rust1", since = "1.0.0")]
18-
impl Ord for str {
18+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
19+
impl const Ord for str {
1920
#[inline]
2021
fn cmp(&self, other: &str) -> Ordering {
2122
self.as_bytes().cmp(other.as_bytes())
@@ -43,7 +44,8 @@ impl const Eq for str {}
4344
/// culturally-accepted standards requires locale-specific data that is outside the scope of
4445
/// the `str` type.
4546
#[stable(feature = "rust1", since = "1.0.0")]
46-
impl PartialOrd for str {
47+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
48+
impl const PartialOrd for str {
4749
#[inline]
4850
fn partial_cmp(&self, other: &str) -> Option<Ordering> {
4951
Some(self.cmp(other))

0 commit comments

Comments
 (0)