constify Step trait and all of its implementations

This commit is contained in:
Lars Schumann
2026-03-13 11:54:06 +00:00
parent 2d76d9bc76
commit 6e2522e6e2
5 changed files with 94 additions and 47 deletions
+4 -2
View File
@@ -405,7 +405,8 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] PartialOrd, const N: usize> const PartialOrd for [T; N] {
#[inline]
fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
PartialOrd::partial_cmp(&&self[..], &&other[..])
@@ -430,7 +431,8 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord, const N: usize> Ord for [T; N] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] Ord, const N: usize> const Ord for [T; N] {
#[inline]
fn cmp(&self, other: &[T; N]) -> Ordering {
Ord::cmp(&&self[..], &&other[..])
+18 -9
View File
@@ -29,7 +29,8 @@ unsafe impl TrustedStep for $type {}
unstable `Step` trait"
)]
#[unstable(feature = "step_trait", issue = "42168")]
pub trait Step: Clone + PartialOrd + Sized {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
pub const trait Step: [const] Clone + [const] PartialOrd + Sized {
/// Returns the bounds on the number of *successor* steps required to get from `start` to `end`
/// like [`Iterator::size_hint()`][Iterator::size_hint()].
///
@@ -262,7 +263,8 @@ macro_rules! step_integer_impls {
$(
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for $u_narrower {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for $u_narrower {
step_identical_methods!();
step_unsigned_methods!();
@@ -296,7 +298,8 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for $i_narrower {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for $i_narrower {
step_identical_methods!();
step_signed_methods!($u_narrower);
@@ -362,7 +365,8 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
$(
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for $u_wider {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for $u_wider {
step_identical_methods!();
step_unsigned_methods!();
@@ -392,7 +396,8 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for $i_wider {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for $i_wider {
step_identical_methods!();
step_signed_methods!($u_wider);
@@ -449,7 +454,8 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
}
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for char {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for char {
#[inline]
fn steps_between(&start: &char, &end: &char) -> (usize, Option<usize>) {
let start = start as u32;
@@ -536,7 +542,8 @@ unsafe fn backward_unchecked(start: char, count: usize) -> char {
}
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for AsciiChar {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for AsciiChar {
#[inline]
fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> (usize, Option<usize>) {
Step::steps_between(&start.to_u8(), &end.to_u8())
@@ -578,7 +585,8 @@ unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
}
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for Ipv4Addr {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for Ipv4Addr {
#[inline]
fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> (usize, Option<usize>) {
u32::steps_between(&start.to_bits(), &end.to_bits())
@@ -610,7 +618,8 @@ unsafe fn backward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
}
#[unstable(feature = "step_trait", issue = "42168")]
impl Step for Ipv6Addr {
#[rustc_const_unstable(feature = "step_trait", issue = "42168")]
impl const Step for Ipv6Addr {
#[inline]
fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> (usize, Option<usize>) {
u128::steps_between(&start.to_bits(), &end.to_bits())
+12 -6
View File
@@ -68,7 +68,8 @@ pub enum IpAddr {
/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
/// ```
#[rustc_diagnostic_item = "Ipv4Addr"]
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy)]
#[derive_const(Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv4Addr {
octets: [u8; 4],
@@ -161,7 +162,8 @@ fn hash<H: Hasher>(&self, state: &mut H) {
/// assert_eq!(localhost.is_loopback(), true);
/// ```
#[rustc_diagnostic_item = "Ipv6Addr"]
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy)]
#[derive_const(Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv6Addr {
octets: [u8; 16],
@@ -1183,7 +1185,8 @@ fn eq(&self, other: &IpAddr) -> bool {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for Ipv4Addr {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const PartialOrd for Ipv4Addr {
#[inline]
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
Some(self.cmp(other))
@@ -1213,7 +1216,8 @@ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Ipv4Addr {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const Ord for Ipv4Addr {
#[inline]
fn cmp(&self, other: &Ipv4Addr) -> Ordering {
self.octets.cmp(&other.octets)
@@ -2177,7 +2181,8 @@ fn eq(&self, other: &Ipv6Addr) -> bool {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for Ipv6Addr {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const PartialOrd for Ipv6Addr {
#[inline]
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
Some(self.cmp(other))
@@ -2207,7 +2212,8 @@ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Ipv6Addr {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const Ord for Ipv6Addr {
#[inline]
fn cmp(&self, other: &Ipv6Addr) -> Ordering {
self.segments().cmp(&other.segments())
+50 -19
View File
@@ -3,7 +3,9 @@
use super::{from_raw_parts, memchr};
use crate::ascii;
use crate::cmp::{self, BytewiseEq, Ordering};
use crate::convert::Infallible;
use crate::intrinsics::compare_bytes;
use crate::marker::Destruct;
use crate::mem::SizedTypeProperties;
use crate::num::NonZero;
use crate::ops::ControlFlow;
@@ -33,7 +35,8 @@ impl<T: [const] Eq> const Eq for [T] {}
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Ord for [T] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] Ord> const Ord for [T] {
fn cmp(&self, other: &[T]) -> Ordering {
SliceOrd::compare(self, other)
}
@@ -52,7 +55,8 @@ const fn as_underlying(x: ControlFlow<bool>) -> u8 {
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for [T] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] PartialOrd> const PartialOrd for [T] {
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
SlicePartialOrd::partial_compare(self, other)
@@ -175,19 +179,31 @@ const trait SliceChain: Sized {
type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
impl<A: PartialOrd> SlicePartialOrd for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] PartialOrd> const SlicePartialOrd for A {
default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) {
Some(Ordering::Equal) => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
};
let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn elem_chain<A: [const] PartialOrd>(a: &A, b: &A) -> ControlFlow<Option<Ordering>> {
match PartialOrd::partial_cmp(a, b) {
Some(Ordering::Equal) => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Option<Ordering>, Infallible> {
ControlFlow::Break(usize::partial_cmp(a, b))
}
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b
}
}
impl<A: PartialOrd> SliceChain for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] PartialOrd> const SliceChain for A {
default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
}
@@ -202,12 +218,13 @@ impl<A: PartialOrd> SliceChain for A {
}
}
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
#[inline]
fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
const fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
left: &'l [A],
right: &'r [A],
elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow<B>,
len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
elem_chain: impl [const] Fn(&'l A, &'r A) -> ControlFlow<B> + [const] Destruct,
len_chain: impl for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C> + [const] Destruct,
) -> ControlFlow<B, C> {
let l = cmp::min(left.len(), right.len());
@@ -216,8 +233,11 @@ fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
let lhs = &left[..l];
let rhs = &right[..l];
for i in 0..l {
// FIXME(const-hack): revert this to `for i in 0..l` once `impl const Iterator for Range<T>`
let mut i: usize = 0;
while i < l {
elem_chain(&lhs[i], &rhs[i])?;
i += 1;
}
len_chain(&left.len(), &right.len())
@@ -270,13 +290,24 @@ const trait SliceOrd: Sized {
fn compare(left: &[Self], right: &[Self]) -> Ordering;
}
impl<A: Ord> SliceOrd for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] Ord> const SliceOrd for A {
default fn compare(left: &[Self], right: &[Self]) -> Ordering {
let elem_chain = |a, b| match Ord::cmp(a, b) {
Ordering::Equal => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
};
let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn elem_chain<A: [const] Ord>(a: &A, b: &A) -> ControlFlow<Ordering> {
match Ord::cmp(a, b) {
Ordering::Equal => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
// FIXME(const-hack): revert this to a const closure once possible
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
const fn len_chain(a: &usize, b: &usize) -> ControlFlow<Ordering, Infallible> {
ControlFlow::Break(usize::cmp(a, b))
}
let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b
}
+10 -11
View File
@@ -39,16 +39,6 @@ pub fn compare() -> bool {
// CHECK: %[[EQ00:.+]] = icmp eq i16 %[[A00]], %[[B00]]
// CHECK-NEXT: br i1 %[[EQ00]], label %[[L01:.+]], label %[[EXIT_S:.+]]
// CHECK: [[L01]]:
// CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2
// CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2
// CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]]
// CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]]
// CHECK-NOT: cmp
// CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]]
// CHECK-NEXT: br i1 %[[EQ01]], label %[[L10:.+]], label %[[EXIT_U:.+]]
// CHECK: [[L10]]:
// CHECK: %[[PA10:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 4
// CHECK: %[[PB10:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 4
// CHECK: %[[A10:.+]] = load i16, ptr %[[PA10]]
@@ -64,7 +54,16 @@ pub fn compare() -> bool {
// CHECK: %[[B11:.+]] = load i16, ptr %[[PB11]]
// CHECK-NOT: cmp
// CHECK: %[[EQ11:.+]] = icmp eq i16 %[[A11]], %[[B11]]
// CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U]]
// CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U:.+]]
// CHECK: [[L01]]:
// CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2
// CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2
// CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]]
// CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]]
// CHECK-NOT: cmp
// CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]]
// CHECK-NEXT: br i1 %[[EQ01]], label %{{.+}}, label %[[EXIT_U]]
// CHECK: [[DONE]]:
// CHECK: %[[RET:.+]] = phi i1 [ %{{.+}}, %[[EXIT_S]] ], [ %{{.+}}, %[[EXIT_U]] ], [ true, %[[L11]] ]