diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 4a2cf15277441..b116841578902 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -405,7 +405,8 @@ where /// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for [T; N] { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for [T; N] { #[inline] fn partial_cmp(&self, other: &[T; N]) -> Option { PartialOrd::partial_cmp(&&self[..], &&other[..]) @@ -430,7 +431,8 @@ impl PartialOrd for [T; N] { /// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for [T; N] { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for [T; N] { #[inline] fn cmp(&self, other: &[T; N]) -> Ordering { Ord::cmp(&&self[..], &&other[..]) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 350b5d31e8940..951bb5d0029f6 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -29,7 +29,8 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6 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 @@ macro_rules! step_integer_impls { #[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 @@ macro_rules! step_integer_impls { $( #[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 @@ macro_rules! step_integer_impls { #[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 @@ step_integer_impls! { } #[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) { let start = start as u32; @@ -536,7 +542,8 @@ impl Step for 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) { Step::steps_between(&start.to_u8(), &end.to_u8()) @@ -578,7 +585,8 @@ impl Step for 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) { u32::steps_between(&start.to_bits(), &end.to_bits()) @@ -610,7 +618,8 @@ impl Step for 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) { u128::steps_between(&start.to_bits(), &end.to_bits()) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index a1bfd774710d5..d18a92208854e 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -68,7 +68,8 @@ pub enum IpAddr { /// assert!("0xcb.0x0.0x71.0x00".parse::().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 @@ impl Hash for Ipv4Addr { /// 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 @@ impl PartialEq for Ipv4Addr { } #[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 { Some(self.cmp(other)) @@ -1213,7 +1216,8 @@ impl PartialOrd for Ipv4Addr { } #[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 @@ impl PartialEq for IpAddr { } #[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 { Some(self.cmp(other)) @@ -2207,7 +2212,8 @@ impl PartialOrd for Ipv6Addr { } #[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()) diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 2390ca74a8e09..69a01eef88f97 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -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 const Eq for [T] {} /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for [T] { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for [T] { fn cmp(&self, other: &[T]) -> Ordering { SliceOrd::compare(self, other) } @@ -52,7 +55,8 @@ const fn as_underlying(x: ControlFlow) -> u8 { /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for [T] { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for [T] { #[inline] fn partial_cmp(&self, other: &[T]) -> Option { SlicePartialOrd::partial_compare(self, other) @@ -175,19 +179,31 @@ const trait SliceChain: Sized { type AlwaysBreak = ControlFlow; -impl SlicePartialOrd for A { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SlicePartialOrd for A { default fn partial_compare(left: &[A], right: &[A]) -> Option { - 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: &A, b: &A) -> ControlFlow> { + 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, Infallible> { + ControlFlow::Break(usize::partial_cmp(a, b)) + } + let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); b } } -impl SliceChain for A { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SliceChain for A { default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow { chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt) } @@ -202,12 +218,13 @@ impl 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, - len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow, + elem_chain: impl [const] Fn(&'l A, &'r A) -> ControlFlow + [const] Destruct, + len_chain: impl for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow + [const] Destruct, ) -> ControlFlow { 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` + 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 SliceOrd for A { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl 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: &A, b: &A) -> ControlFlow { + 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 { + ControlFlow::Break(usize::cmp(a, b)) + } + let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); b } diff --git a/tests/codegen-llvm/array-cmp.rs b/tests/codegen-llvm/array-cmp.rs index 0d33765540176..0106b9c15c11b 100644 --- a/tests/codegen-llvm/array-cmp.rs +++ b/tests/codegen-llvm/array-cmp.rs @@ -39,16 +39,6 @@ pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> 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 array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> 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]] ]