diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index ff46bb13ba4eb..200b94c9d3b5d 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -6,7 +6,8 @@ use crate::slice::SliceIndex; use crate::{hash, ops, range}; #[unstable(feature = "bstr", issue = "134915")] -impl Ord for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for ByteStr { #[inline] fn cmp(&self, other: &ByteStr) -> Ordering { Ord::cmp(&self.0, &other.0) @@ -14,7 +15,8 @@ impl Ord for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl PartialOrd for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for ByteStr { #[inline] fn partial_cmp(&self, other: &ByteStr) -> Option { PartialOrd::partial_cmp(&self.0, &other.0) @@ -22,7 +24,8 @@ impl PartialOrd for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl PartialEq for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for ByteStr { #[inline] fn eq(&self, other: &ByteStr) -> bool { &self.0 == &other.0 @@ -30,7 +33,8 @@ impl PartialEq for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl Eq for ByteStr {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for ByteStr {} #[unstable(feature = "bstr", issue = "134915")] impl hash::Hash for ByteStr { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 09d9b160700ca..176353d1a3246 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -88,7 +88,8 @@ use crate::{fmt, ops, slice, str}; /// ``` /// /// [str]: prim@str "str" -#[derive(PartialEq, Eq, Hash)] +#[derive(Hash)] +#[derive_const(PartialEq, Eq)] #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_diagnostic_item = "cstr_type"] #[rustc_has_incoherent_inherent_impls] @@ -667,7 +668,8 @@ impl PartialEq<&Self> for CStr { // because `c_char` is `i8` (not `u8`) on some platforms. // That is why this is implemented manually and not derived. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for CStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for CStr { #[inline] fn partial_cmp(&self, other: &CStr) -> Option { self.to_bytes().partial_cmp(&other.to_bytes()) @@ -675,7 +677,8 @@ impl PartialOrd for CStr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for CStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for CStr { #[inline] fn cmp(&self, other: &CStr) -> Ordering { self.to_bytes().cmp(&other.to_bytes()) diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 5935849344475..759cc2b5bbfa9 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -47,7 +47,8 @@ pub struct Location<'a> { } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl PartialEq for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for Location<'_> { fn eq(&self, other: &Self) -> bool { // Compare col / line first as they're cheaper to compare and more likely to differ, // while not impacting the result. @@ -56,20 +57,29 @@ impl PartialEq for Location<'_> { } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl Eq for Location<'_> {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for Location<'_> {} #[stable(feature = "panic_hooks", since = "1.10.0")] -impl Ord for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for Location<'_> { fn cmp(&self, other: &Self) -> Ordering { - self.file() - .cmp(other.file()) - .then_with(|| self.line.cmp(&other.line)) - .then_with(|| self.col.cmp(&other.col)) + // FIXME(const-hack): This uses match instead of `then_with` as a + // workaround for the lack of const closures. Revert to using + // `then_with` once const closures are available. + match self.file().cmp(other.file()) { + Ordering::Equal => match self.line.cmp(&other.line) { + Ordering::Equal => self.col.cmp(&other.col), + ordering => ordering, + }, + ordering => ordering, + } } } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl PartialOrd for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Location<'_> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 103630aba0f79..4a33596685b2f 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::num::NonZero; use crate::ops::ControlFlow; @@ -28,7 +30,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) } @@ -47,7 +50,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) @@ -155,39 +159,50 @@ where } #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's PartialOrd -trait SlicePartialOrd: Sized { +const trait SlicePartialOrd: Sized { fn partial_compare(left: &[Self], right: &[Self]) -> Option; } #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's PartialOrd chaining methods -trait SliceChain: Sized { +const trait SliceChain: Sized { fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow; fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow; fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow; fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow; } -type AlwaysBreak = ControlFlow; +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)); + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + const fn elem_chain(a: &B, b: &B) -> ControlFlow> + where + B: [const] PartialOrd, + { + match a.partial_cmp(b) { + Some(Ordering::Equal) => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + } + } + + #[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) } @@ -203,12 +218,17 @@ impl SliceChain for A { } #[inline] -fn chaining_impl<'l, 'r, A: PartialOrd, B, C>( +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const fn chaining_impl<'l, 'r, A: PartialOrd, B, C, E, L>( 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, -) -> ControlFlow { + elem_chain: E, + len_chain: L, +) -> ControlFlow +where + E: [const] Destruct + [const] Fn(&'l A, &'r A) -> ControlFlow, + L: [const] Destruct + for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow, +{ let l = cmp::min(left.len(), right.len()); // Slice to the loop iteration range to enable bound check @@ -216,8 +236,13 @@ 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): This uses a `while` loop instead of `for` as a + // workaround for the lack of const iterators. Revert to using `for` once + // const iterators are available. + let mut i = 0; + while i < l { elem_chain(&lhs[i], &rhs[i])?; + i += 1; } len_chain(&left.len(), &right.len()) @@ -244,13 +269,15 @@ impl const SlicePartialOrd for A { } #[rustc_specialization_trait] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} +const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} macro_rules! always_applicable_ord { ($([$($p:tt)*] $t:ty,)*) => { - $(impl<$($p)*> AlwaysApplicableOrd for $t {})* + $( + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl<$($p)*> const AlwaysApplicableOrd for $t {} + )* } } @@ -258,27 +285,40 @@ always_applicable_ord! { [] u8, [] u16, [] u32, [] u64, [] u128, [] usize, [] i8, [] i16, [] i32, [] i64, [] i128, [] isize, [] bool, [] char, - [T: ?Sized] *const T, [T: ?Sized] *mut T, - [T: AlwaysApplicableOrd] &T, - [T: AlwaysApplicableOrd] &mut T, - [T: AlwaysApplicableOrd] Option, + [T: [const] AlwaysApplicableOrd] &T, + [T: [const] AlwaysApplicableOrd] &mut T, + [T: [const] AlwaysApplicableOrd] Option, } +impl AlwaysApplicableOrd for *const T {} +impl AlwaysApplicableOrd for *mut T {} + #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's Ord -trait SliceOrd: Sized { +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)); + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + const fn elem_chain(a: &B, b: &B) -> ControlFlow + where + B: [const] Ord, + { + match a.cmp(b) { + Ordering::Equal => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + } + } + + #[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 } @@ -334,7 +374,6 @@ impl const SliceOrd for A { } // Don't generate our own chaining loops for `memcmp`-able things either. - #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl const SliceChain for A { #[inline] diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index a7cc943994c53..805f34855ef65 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -15,7 +15,8 @@ use crate::{ops, ptr, range}; /// culturally-accepted standards requires locale-specific data that is outside the scope of /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for str { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for str { #[inline] fn cmp(&self, other: &str) -> Ordering { self.as_bytes().cmp(other.as_bytes()) @@ -43,7 +44,8 @@ impl const Eq for str {} /// culturally-accepted standards requires locale-specific data that is outside the scope of /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for str { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for str { #[inline] fn partial_cmp(&self, other: &str) -> Option { Some(self.cmp(other))