authorbors <bors@rust-lang.org> 2026-03-28 10:44:18 UTC
committerbors <bors@rust-lang.org> 2026-03-28 10:44:18 UTC
log7e28c7438a7b0c79a09724ba799d32ed461beb72
treebac93e10da89d000a8a47c40b33ac08a11924403
parent79531c53ded6316bd4973f60bc992954255b8b10
parent6e2522e6e23fb5195d1413e79d077b66a5c1a3a2

Auto merge of #153821 - Lars-Schumann:const-step, r=Mark-Simulacrum

constify `Step` trait and all of its `impl`ementations constifying [Step](https://github.com/rust-lang/rust/issues/42168) trait and all of its implementations, with some friendly help from [const_cmp](https://github.com/rust-lang/rust/issues/143800)

5 files changed, 94 insertions(+), 47 deletions(-)

library/core/src/array/mod.rs+4-2
......@@ -405,7 +405,8 @@ where
405405
406406/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
407407#[stable(feature = "rust1", since = "1.0.0")]
408impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
408#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
409impl<T: [const] PartialOrd, const N: usize> const PartialOrd for [T; N] {
409410 #[inline]
410411 fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
411412 PartialOrd::partial_cmp(&&self[..], &&other[..])
......@@ -430,7 +431,8 @@ impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
430431
431432/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
432433#[stable(feature = "rust1", since = "1.0.0")]
433impl<T: Ord, const N: usize> Ord for [T; N] {
434#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
435impl<T: [const] Ord, const N: usize> const Ord for [T; N] {
434436 #[inline]
435437 fn cmp(&self, other: &[T; N]) -> Ordering {
436438 Ord::cmp(&&self[..], &&other[..])
library/core/src/iter/range.rs+18-9
......@@ -29,7 +29,8 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
2929 unstable `Step` trait"
3030)]
3131#[unstable(feature = "step_trait", issue = "42168")]
32pub trait Step: Clone + PartialOrd + Sized {
32#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
33pub const trait Step: [const] Clone + [const] PartialOrd + Sized {
3334 /// Returns the bounds on the number of *successor* steps required to get from `start` to `end`
3435 /// like [`Iterator::size_hint()`][Iterator::size_hint()].
3536 ///
......@@ -262,7 +263,8 @@ macro_rules! step_integer_impls {
262263 $(
263264 #[allow(unreachable_patterns)]
264265 #[unstable(feature = "step_trait", issue = "42168")]
265 impl Step for $u_narrower {
266 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
267 impl const Step for $u_narrower {
266268 step_identical_methods!();
267269 step_unsigned_methods!();
268270
......@@ -296,7 +298,8 @@ macro_rules! step_integer_impls {
296298
297299 #[allow(unreachable_patterns)]
298300 #[unstable(feature = "step_trait", issue = "42168")]
299 impl Step for $i_narrower {
301 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
302 impl const Step for $i_narrower {
300303 step_identical_methods!();
301304 step_signed_methods!($u_narrower);
302305
......@@ -362,7 +365,8 @@ macro_rules! step_integer_impls {
362365 $(
363366 #[allow(unreachable_patterns)]
364367 #[unstable(feature = "step_trait", issue = "42168")]
365 impl Step for $u_wider {
368 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
369 impl const Step for $u_wider {
366370 step_identical_methods!();
367371 step_unsigned_methods!();
368372
......@@ -392,7 +396,8 @@ macro_rules! step_integer_impls {
392396
393397 #[allow(unreachable_patterns)]
394398 #[unstable(feature = "step_trait", issue = "42168")]
395 impl Step for $i_wider {
399 #[rustc_const_unstable(feature = "step_trait", issue = "42168")]
400 impl const Step for $i_wider {
396401 step_identical_methods!();
397402 step_signed_methods!($u_wider);
398403
......@@ -449,7 +454,8 @@ step_integer_impls! {
449454}
450455
451456#[unstable(feature = "step_trait", issue = "42168")]
452impl Step for char {
457#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
458impl const Step for char {
453459 #[inline]
454460 fn steps_between(&start: &char, &end: &char) -> (usize, Option<usize>) {
455461 let start = start as u32;
......@@ -536,7 +542,8 @@ impl Step for char {
536542}
537543
538544#[unstable(feature = "step_trait", issue = "42168")]
539impl Step for AsciiChar {
545#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
546impl const Step for AsciiChar {
540547 #[inline]
541548 fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> (usize, Option<usize>) {
542549 Step::steps_between(&start.to_u8(), &end.to_u8())
......@@ -578,7 +585,8 @@ impl Step for AsciiChar {
578585}
579586
580587#[unstable(feature = "step_trait", issue = "42168")]
581impl Step for Ipv4Addr {
588#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
589impl const Step for Ipv4Addr {
582590 #[inline]
583591 fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> (usize, Option<usize>) {
584592 u32::steps_between(&start.to_bits(), &end.to_bits())
......@@ -610,7 +618,8 @@ impl Step for Ipv4Addr {
610618}
611619
612620#[unstable(feature = "step_trait", issue = "42168")]
613impl Step for Ipv6Addr {
621#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
622impl const Step for Ipv6Addr {
614623 #[inline]
615624 fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> (usize, Option<usize>) {
616625 u128::steps_between(&start.to_bits(), &end.to_bits())
library/core/src/net/ip_addr.rs+12-6
......@@ -68,7 +68,8 @@ pub enum IpAddr {
6868/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
6969/// ```
7070#[rustc_diagnostic_item = "Ipv4Addr"]
71#[derive(Copy, Clone, PartialEq, Eq)]
71#[derive(Copy)]
72#[derive_const(Clone, PartialEq, Eq)]
7273#[stable(feature = "rust1", since = "1.0.0")]
7374pub struct Ipv4Addr {
7475 octets: [u8; 4],
......@@ -161,7 +162,8 @@ impl Hash for Ipv4Addr {
161162/// assert_eq!(localhost.is_loopback(), true);
162163/// ```
163164#[rustc_diagnostic_item = "Ipv6Addr"]
164#[derive(Copy, Clone, PartialEq, Eq)]
165#[derive(Copy)]
166#[derive_const(Clone, PartialEq, Eq)]
165167#[stable(feature = "rust1", since = "1.0.0")]
166168pub struct Ipv6Addr {
167169 octets: [u8; 16],
......@@ -1229,7 +1231,8 @@ impl PartialEq<IpAddr> for Ipv4Addr {
12291231}
12301232
12311233#[stable(feature = "rust1", since = "1.0.0")]
1232impl PartialOrd for Ipv4Addr {
1234#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1235impl const PartialOrd for Ipv4Addr {
12331236 #[inline]
12341237 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
12351238 Some(self.cmp(other))
......@@ -1259,7 +1262,8 @@ impl PartialOrd<IpAddr> for Ipv4Addr {
12591262}
12601263
12611264#[stable(feature = "rust1", since = "1.0.0")]
1262impl Ord for Ipv4Addr {
1265#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1266impl const Ord for Ipv4Addr {
12631267 #[inline]
12641268 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
12651269 self.octets.cmp(&other.octets)
......@@ -2232,7 +2236,8 @@ impl PartialEq<Ipv6Addr> for IpAddr {
22322236}
22332237
22342238#[stable(feature = "rust1", since = "1.0.0")]
2235impl PartialOrd for Ipv6Addr {
2239#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2240impl const PartialOrd for Ipv6Addr {
22362241 #[inline]
22372242 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
22382243 Some(self.cmp(other))
......@@ -2262,7 +2267,8 @@ impl PartialOrd<IpAddr> for Ipv6Addr {
22622267}
22632268
22642269#[stable(feature = "rust1", since = "1.0.0")]
2265impl Ord for Ipv6Addr {
2270#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2271impl const Ord for Ipv6Addr {
22662272 #[inline]
22672273 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
22682274 self.segments().cmp(&other.segments())
library/core/src/slice/cmp.rs+50-19
......@@ -3,7 +3,9 @@
33use super::{from_raw_parts, memchr};
44use crate::ascii;
55use crate::cmp::{self, BytewiseEq, Ordering};
6use crate::convert::Infallible;
67use crate::intrinsics::compare_bytes;
8use crate::marker::Destruct;
79use crate::mem::SizedTypeProperties;
810use crate::num::NonZero;
911use crate::ops::ControlFlow;
......@@ -33,7 +35,8 @@ impl<T: [const] Eq> const Eq for [T] {}
3335
3436/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
3537#[stable(feature = "rust1", since = "1.0.0")]
36impl<T: Ord> Ord for [T] {
38#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
39impl<T: [const] Ord> const Ord for [T] {
3740 fn cmp(&self, other: &[T]) -> Ordering {
3841 SliceOrd::compare(self, other)
3942 }
......@@ -52,7 +55,8 @@ const fn as_underlying(x: ControlFlow<bool>) -> u8 {
5255
5356/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
5457#[stable(feature = "rust1", since = "1.0.0")]
55impl<T: PartialOrd> PartialOrd for [T] {
58#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
59impl<T: [const] PartialOrd> const PartialOrd for [T] {
5660 #[inline]
5761 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
5862 SlicePartialOrd::partial_compare(self, other)
......@@ -175,19 +179,31 @@ const trait SliceChain: Sized {
175179
176180type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
177181
178impl<A: PartialOrd> SlicePartialOrd for A {
182#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
183impl<A: [const] PartialOrd> const SlicePartialOrd for A {
179184 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));
185 // FIXME(const-hack): revert this to a const closure once possible
186 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
187 const fn elem_chain<A: [const] PartialOrd>(a: &A, b: &A) -> ControlFlow<Option<Ordering>> {
188 match PartialOrd::partial_cmp(a, b) {
189 Some(Ordering::Equal) => ControlFlow::Continue(()),
190 non_eq => ControlFlow::Break(non_eq),
191 }
192 }
193
194 // FIXME(const-hack): revert this to a const closure once possible
195 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
196 const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Option<Ordering>, Infallible> {
197 ControlFlow::Break(usize::partial_cmp(a, b))
198 }
199
185200 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
186201 b
187202 }
188203}
189204
190impl<A: PartialOrd> SliceChain for A {
205#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
206impl<A: [const] PartialOrd> const SliceChain for A {
191207 default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
192208 chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
193209 }
......@@ -202,12 +218,13 @@ impl<A: PartialOrd> SliceChain for A {
202218 }
203219}
204220
221#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
205222#[inline]
206fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
223const fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
207224 left: &'l [A],
208225 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>,
226 elem_chain: impl [const] Fn(&'l A, &'r A) -> ControlFlow<B> + [const] Destruct,
227 len_chain: impl for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C> + [const] Destruct,
211228) -> ControlFlow<B, C> {
212229 let l = cmp::min(left.len(), right.len());
213230
......@@ -216,8 +233,11 @@ fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
216233 let lhs = &left[..l];
217234 let rhs = &right[..l];
218235
219 for i in 0..l {
236 // FIXME(const-hack): revert this to `for i in 0..l` once `impl const Iterator for Range<T>`
237 let mut i: usize = 0;
238 while i < l {
220239 elem_chain(&lhs[i], &rhs[i])?;
240 i += 1;
221241 }
222242
223243 len_chain(&left.len(), &right.len())
......@@ -270,13 +290,24 @@ const trait SliceOrd: Sized {
270290 fn compare(left: &[Self], right: &[Self]) -> Ordering;
271291}
272292
273impl<A: Ord> SliceOrd for A {
293#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
294impl<A: [const] Ord> const SliceOrd for A {
274295 default fn compare(left: &[Self], right: &[Self]) -> Ordering {
275 let elem_chain = |a, b| match Ord::cmp(a, b) {
276 Ordering::Equal => ControlFlow::Continue(()),
277 non_eq => ControlFlow::Break(non_eq),
278 };
279 let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
296 // FIXME(const-hack): revert this to a const closure once possible
297 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
298 const fn elem_chain<A: [const] Ord>(a: &A, b: &A) -> ControlFlow<Ordering> {
299 match Ord::cmp(a, b) {
300 Ordering::Equal => ControlFlow::Continue(()),
301 non_eq => ControlFlow::Break(non_eq),
302 }
303 }
304
305 // FIXME(const-hack): revert this to a const closure once possible
306 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
307 const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Ordering, Infallible> {
308 ControlFlow::Break(usize::cmp(a, b))
309 }
310
280311 let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
281312 b
282313 }
tests/codegen-llvm/array-cmp.rs+10-11
......@@ -39,16 +39,6 @@ pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool {
3939 // CHECK: %[[EQ00:.+]] = icmp eq i16 %[[A00]], %[[B00]]
4040 // CHECK-NEXT: br i1 %[[EQ00]], label %[[L01:.+]], label %[[EXIT_S:.+]]
4141
42 // CHECK: [[L01]]:
43 // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2
44 // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2
45 // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]]
46 // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]]
47 // CHECK-NOT: cmp
48 // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]]
49 // CHECK-NEXT: br i1 %[[EQ01]], label %[[L10:.+]], label %[[EXIT_U:.+]]
50
51 // CHECK: [[L10]]:
5242 // CHECK: %[[PA10:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 4
5343 // CHECK: %[[PB10:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 4
5444 // CHECK: %[[A10:.+]] = load i16, ptr %[[PA10]]
......@@ -64,7 +54,16 @@ pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool {
6454 // CHECK: %[[B11:.+]] = load i16, ptr %[[PB11]]
6555 // CHECK-NOT: cmp
6656 // CHECK: %[[EQ11:.+]] = icmp eq i16 %[[A11]], %[[B11]]
67 // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U]]
57 // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U:.+]]
58
59 // CHECK: [[L01]]:
60 // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2
61 // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2
62 // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]]
63 // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]]
64 // CHECK-NOT: cmp
65 // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]]
66 // CHECK-NEXT: br i1 %[[EQ01]], label %{{.+}}, label %[[EXIT_U]]
6867
6968 // CHECK: [[DONE]]:
7069 // CHECK: %[[RET:.+]] = phi i1 [ %{{.+}}, %[[EXIT_S]] ], [ %{{.+}}, %[[EXIT_U]] ], [ true, %[[L11]] ]