From 98f3ec87181567a3b66867b30375ebab1a87159f Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Sun, 3 Aug 2025 20:28:23 +0300 Subject: [PATCH] Constify Eq, Ord, PartialOrd --- library/core/src/alloc/layout.rs | 3 +- library/core/src/alloc/mod.rs | 3 +- library/core/src/any.rs | 3 +- library/core/src/array/equality.rs | 46 +++-- library/core/src/array/mod.rs | 18 +- library/core/src/ascii/ascii_char.rs | 3 +- library/core/src/char/convert.rs | 9 +- library/core/src/char/decode.rs | 3 +- library/core/src/char/mod.rs | 3 +- library/core/src/cmp.rs | 162 ++++++++++++------ library/core/src/convert/mod.rs | 9 +- library/core/src/intrinsics/mod.rs | 3 +- library/core/src/marker.rs | 3 +- library/core/src/mem/manually_drop.rs | 3 +- library/core/src/mem/transmutability.rs | 3 +- library/core/src/num/dec2flt/decimal.rs | 3 +- library/core/src/num/niche_types.rs | 13 +- library/core/src/num/nonzero.rs | 17 +- library/core/src/ops/control_flow.rs | 9 +- library/core/src/ops/coroutine.rs | 3 +- library/core/src/option.rs | 9 +- library/core/src/ptr/alignment.rs | 12 +- library/core/src/range.rs | 6 +- library/core/src/result.rs | 3 +- library/core/src/slice/cmp.rs | 65 +++++-- library/core/src/str/lossy.rs | 3 +- library/core/src/str/pattern.rs | 3 +- library/core/src/str/traits.rs | 3 +- library/core/src/sync/atomic.rs | 3 +- library/core/src/time.rs | 6 +- library/coretests/tests/cmp.rs | 6 +- library/coretests/tests/lib.rs | 1 + tests/ui/consts/const_cmp_type_id.rs | 5 +- tests/ui/consts/const_cmp_type_id.stderr | 8 +- .../traits/const-traits/const-impl-trait.rs | 4 +- .../const-traits/const-impl-trait.stderr | 17 -- .../const_derives/derive-const-use.rs | 3 +- .../const_derives/derive-const-use.stderr | 11 -- 38 files changed, 302 insertions(+), 185 deletions(-) delete mode 100644 tests/ui/traits/const-traits/const-impl-trait.stderr delete mode 100644 tests/ui/traits/const-traits/const_derives/derive-const-use.stderr diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 49275975f046f..8facdaff63416 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -35,7 +35,8 @@ const fn size_align() -> (usize, usize) { /// like this are met, use specific allocators with looser /// requirements, or use the more lenient `Allocator` interface.) #[stable(feature = "alloc_layout", since = "1.28.0")] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, Eq)] #[lang = "alloc_layout"] pub struct Layout { // size of the requested block of memory, measured in bytes. diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 9d608d5e83c40..0ad2c98d1145f 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -28,7 +28,8 @@ use crate::ptr::{self, NonNull}; /// something wrong when combining the given input arguments with this /// allocator. #[unstable(feature = "allocator_api", issue = "32838")] -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub struct AllocError; #[unstable( diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 38393379a78a7..da0e9d14cd77a 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -705,7 +705,8 @@ impl dyn Any + Send + Sync { /// std::mem::forget(fake_one_ring); /// } /// ``` -#[derive(Clone, Copy, Eq, PartialOrd, Ord)] +#[derive(Copy, PartialOrd, Ord)] +#[derive_const(Clone, Eq)] #[stable(feature = "rust1", since = "1.0.0")] #[lang = "type_id"] pub struct TypeId { diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index bb668d2a67309..426191a75f06a 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -1,9 +1,10 @@ use crate::cmp::BytewiseEq; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U; N]> for [T; N] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U; N]> for [T; N] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &[U; N]) -> bool { @@ -16,9 +17,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U]> for [T; N] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U]> for [T; N] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &[U]) -> bool { @@ -39,9 +41,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U; N]> for [T] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U; N]> for [T] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &[U; N]) -> bool { @@ -62,9 +65,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&[U]> for [T; N] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<&[U]> for [T; N] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &&[U]) -> bool { @@ -77,9 +81,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U; N]> for &[T] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U; N]> for &[T] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &[U; N]) -> bool { @@ -92,9 +97,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&mut [U]> for [T; N] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<&mut [U]> for [T; N] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &&mut [U]) -> bool { @@ -107,9 +113,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[U; N]> for &mut [T] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq<[U; N]> for &mut [T] where - T: PartialEq, + T: ~const PartialEq, { #[inline] fn eq(&self, other: &[U; N]) -> bool { @@ -126,14 +133,18 @@ where // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for [T; N] {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for [T; N] {} +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] trait SpecArrayEq: Sized { fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; } -impl, Other, const N: usize> SpecArrayEq for T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl, Other, const N: usize> const SpecArrayEq for T { default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool { a[..] == b[..] } @@ -142,7 +153,8 @@ impl, Other, const N: usize> SpecArrayEq for T { } } -impl, U, const N: usize> SpecArrayEq for T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl, U, const N: usize> const SpecArrayEq for T { fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { // SAFETY: Arrays are compared element-wise, and don't add any padding // between elements, so when the elements are `BytewiseEq`, we can diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 1c23218552aa1..685358e5054f6 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -206,7 +206,8 @@ impl const From for TryFromSliceError { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[T]> for [T; N] { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl const AsRef<[T]> for [T; N] { #[inline] fn as_ref(&self) -> &[T] { &self[..] @@ -214,7 +215,8 @@ impl AsRef<[T]> for [T; N] { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsMut<[T]> for [T; N] { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl const AsMut<[T]> for [T; N] { #[inline] fn as_mut(&mut self) -> &mut [T] { &mut self[..] @@ -248,7 +250,8 @@ impl BorrowMut<[T]> for [T; N] { /// assert_eq!(512, u16::from_le_bytes(bytes_tail)); /// ``` #[stable(feature = "try_from", since = "1.34.0")] -impl TryFrom<&[T]> for [T; N] +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl const TryFrom<&[T]> for [T; N] where T: Copy, { @@ -273,7 +276,8 @@ where /// assert_eq!(512, u16::from_le_bytes(bytes_tail)); /// ``` #[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")] -impl TryFrom<&mut [T]> for [T; N] +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl const TryFrom<&mut [T]> for [T; N] where T: Copy, { @@ -298,7 +302,8 @@ where /// assert_eq!(512, u16::from_le_bytes(*bytes_tail)); /// ``` #[stable(feature = "try_from", since = "1.34.0")] -impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T, const N: usize> const TryFrom<&'a [T]> for &'a [T; N] { type Error = TryFromSliceError; #[inline] @@ -320,7 +325,8 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { /// assert_eq!(512, u16::from_le_bytes(*bytes_tail)); /// ``` #[stable(feature = "try_from", since = "1.34.0")] -impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { +#[rustc_const_unstable(feature = "const_from", issue = "143773")] +impl<'a, T, const N: usize> const TryFrom<&'a mut [T]> for &'a mut [T; N] { type Error = TryFromSliceError; #[inline] diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 054ddf844700e..c96dead981bb5 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -54,7 +54,8 @@ use crate::{assert_unsafe_precondition, fmt}; /// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf /// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf /// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, Eq, PartialEq, Ord, PartialOrd)] #[unstable(feature = "ascii_char", issue = "110998")] #[repr(u8)] pub enum AsciiChar { diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 23061cb663bc6..f1e47da002980 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -181,12 +181,14 @@ impl const From for char { /// /// This `struct` is created when using the [`char::from_str`] method. #[stable(feature = "char_from_str", since = "1.20.0")] -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub struct ParseCharError { kind: CharErrorKind, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] enum CharErrorKind { EmptyString, TooManyChars, @@ -266,7 +268,8 @@ impl const TryFrom for char { /// This `struct` is created by the [`char::try_from`](char#impl-TryFrom-for-char) method. /// See its documentation for more. #[stable(feature = "try_from", since = "1.34.0")] -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub struct CharTryFromError(()); #[stable(feature = "try_from", since = "1.34.0")] diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index 23319fbe5ddc4..f6ce4be090219 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -24,7 +24,8 @@ where /// /// This `struct` is created when using the [`DecodeUtf16`] type. #[stable(feature = "decode_utf16", since = "1.9.0")] -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Clone, Debug)] +#[derive_const(Eq, PartialEq)] pub struct DecodeUtf16Error { code: u16, } diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 82a3f6f916be3..4d29e0e6813e5 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -591,7 +591,8 @@ impl fmt::Display for CaseMappingIter { /// The error type returned when a checked char conversion fails. #[stable(feature = "u8_from_char", since = "1.59.0")] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub struct TryFromCharError(pub(crate) ()); #[stable(feature = "u8_from_char", since = "1.59.0")] diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 1b9af10a6fda5..63ef55540967e 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -29,7 +29,7 @@ mod bytewise; pub(crate) use bytewise::BytewiseEq; use self::Ordering::*; -use crate::marker::PointeeSized; +use crate::marker::{Destruct, PointeeSized}; use crate::ops::ControlFlow; /// Trait for comparisons using the equality operator. @@ -335,7 +335,9 @@ pub macro PartialEq($item:item) { #[doc(alias = "!=")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Eq"] -pub trait Eq: PartialEq + PointeeSized { +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub trait Eq: ~const PartialEq + PointeeSized { // this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a // type implements `Eq` itself. The current deriving infrastructure means doing this assertion // without using a method on this trait is nearly impossible. @@ -381,8 +383,8 @@ pub struct AssertParamIsEq { /// /// assert_eq!(2.cmp(&1), Ordering::Greater); /// ``` -#[derive(Clone, Copy, Eq, PartialOrd, Ord, Debug, Hash)] -#[derive_const(PartialEq)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, Eq, PartialOrd, Ord, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] // This is a lang item only so that `BinOp::Cmp` in MIR can return it. // It has no special behavior, but does require that the three variants @@ -636,7 +638,11 @@ impl Ordering { #[inline] #[must_use] #[stable(feature = "ordering_chaining", since = "1.17.0")] - pub fn then_with Ordering>(self, f: F) -> Ordering { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + pub const fn then_with(self, f: F) -> Ordering + where + F: ~const FnOnce() -> Ordering + ~const Destruct, + { match self { Equal => f(), _ => self, @@ -660,13 +666,15 @@ impl Ordering { /// v.sort_by_key(|&num| (num > 3, Reverse(num))); /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]); /// ``` -#[derive(PartialEq, Eq, Debug, Copy, Default, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(PartialEq, Eq, Default)] #[stable(feature = "reverse_cmp_key", since = "1.19.0")] #[repr(transparent)] pub struct Reverse(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); #[stable(feature = "reverse_cmp_key", since = "1.19.0")] -impl PartialOrd for Reverse { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Reverse { #[inline] fn partial_cmp(&self, other: &Reverse) -> Option { other.0.partial_cmp(&self.0) @@ -691,7 +699,8 @@ impl PartialOrd for Reverse { } #[stable(feature = "reverse_cmp_key", since = "1.19.0")] -impl Ord for Reverse { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for Reverse { #[inline] fn cmp(&self, other: &Reverse) -> Ordering { other.0.cmp(&self.0) @@ -958,7 +967,9 @@ impl Clone for Reverse { #[doc(alias = ">=")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Ord"] -pub trait Ord: Eq + PartialOrd + PointeeSized { +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub trait Ord: ~const Eq + ~const PartialOrd + PointeeSized { /// This method returns an [`Ordering`] between `self` and `other`. /// /// By convention, `self.cmp(&other)` returns the ordering matching the expression @@ -1012,7 +1023,7 @@ pub trait Ord: Eq + PartialOrd + PointeeSized { #[rustc_diagnostic_item = "cmp_ord_max"] fn max(self, other: Self) -> Self where - Self: Sized, + Self: Sized + ~const Destruct + ~const PartialOrd, { if other < self { self } else { other } } @@ -1051,7 +1062,7 @@ pub trait Ord: Eq + PartialOrd + PointeeSized { #[rustc_diagnostic_item = "cmp_ord_min"] fn min(self, other: Self) -> Self where - Self: Sized, + Self: Sized + ~const Destruct + ~const PartialOrd, { if other < self { other } else { self } } @@ -1077,7 +1088,7 @@ pub trait Ord: Eq + PartialOrd + PointeeSized { #[stable(feature = "clamp", since = "1.50.0")] fn clamp(self, min: Self, max: Self) -> Self where - Self: Sized, + Self: Sized + ~const Destruct + ~const PartialOrd, { assert!(min <= max); if self < min { @@ -1342,6 +1353,8 @@ pub macro Ord($item:item) { )] #[rustc_diagnostic_item = "PartialOrd"] #[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] pub trait PartialOrd: PartialEq + PointeeSized { /// This method returns an ordering between `self` and `other` values if one exists. /// @@ -1482,13 +1495,14 @@ pub trait PartialOrd: PartialEq + PointeeSized { } } -fn default_chaining_impl( +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const fn default_chaining_impl( lhs: &T, rhs: &U, - p: impl FnOnce(Ordering) -> bool, + p: impl ~const FnOnce(Ordering) -> bool + ~const Destruct, ) -> ControlFlow where - T: PartialOrd + PointeeSized, + T: ~const PartialOrd + PointeeSized, U: PointeeSized, { // It's important that this only call `partial_cmp` once, not call `eq` then @@ -1546,7 +1560,8 @@ pub macro PartialOrd($item:item) { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "cmp_min"] -pub fn min(v1: T, v2: T) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn min(v1: T, v2: T) -> T { v1.min(v2) } @@ -1573,7 +1588,12 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn min_by Ordering>( + v1: T, + v2: T, + compare: F, +) -> T { if compare(&v2, &v1).is_lt() { v2 } else { v1 } } @@ -1598,7 +1618,13 @@ pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn min_by_key(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const FnMut(&T) -> K + ~const Destruct, + K: ~const Ord + ~const Destruct, +{ if f(&v2) < f(&v1) { v2 } else { v1 } } @@ -1638,7 +1664,8 @@ pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "cmp_max"] -pub fn max(v1: T, v2: T) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn max(v1: T, v2: T) -> T { v1.max(v2) } @@ -1665,7 +1692,12 @@ pub fn max(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn max_by Ordering>( + v1: T, + v2: T, + compare: F, +) -> T { if compare(&v2, &v1).is_lt() { v1 } else { v2 } } @@ -1690,7 +1722,13 @@ pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn max_by_key(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const FnMut(&T) -> K + ~const Destruct, + K: ~const Ord + ~const Destruct, +{ if f(&v2) < f(&v1) { v1 } else { v2 } } @@ -1734,9 +1772,10 @@ pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[inline] #[must_use] #[unstable(feature = "cmp_minmax", issue = "115939")] -pub fn minmax(v1: T, v2: T) -> [T; 2] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn minmax(v1: T, v2: T) -> [T; 2] where - T: Ord, + T: ~const Ord, { if v2 < v1 { [v2, v1] } else { [v1, v2] } } @@ -1765,9 +1804,10 @@ where #[inline] #[must_use] #[unstable(feature = "cmp_minmax", issue = "115939")] -pub fn minmax_by(v1: T, v2: T, compare: F) -> [T; 2] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn minmax_by(v1: T, v2: T, compare: F) -> [T; 2] where - F: FnOnce(&T, &T) -> Ordering, + F: ~const FnOnce(&T, &T) -> Ordering, { if compare(&v2, &v1).is_lt() { [v2, v1] } else { [v1, v2] } } @@ -1793,10 +1833,11 @@ where #[inline] #[must_use] #[unstable(feature = "cmp_minmax", issue = "115939")] -pub fn minmax_by_key(v1: T, v2: T, mut f: F) -> [T; 2] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +pub const fn minmax_by_key(v1: T, v2: T, mut f: F) -> [T; 2] where - F: FnMut(&T) -> K, - K: Ord, + F: ~const FnMut(&T) -> K + ~const Destruct, + K: ~const Ord + ~const Destruct, { if f(&v2) < f(&v1) { [v2, v1] } else { [v1, v2] } } @@ -1822,7 +1863,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialEq for () { #[inline] fn eq(&self, _other: &()) -> bool { true @@ -1840,7 +1882,8 @@ mod impls { macro_rules! eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Eq for $t {} + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Eq for $t {} )*) } @@ -1888,7 +1931,8 @@ mod impls { macro_rules! partial_ord_impl { ($($t:ty)*) => ($( #[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: &Self) -> Option { match (*self <= *other, *self >= *other) { @@ -1905,7 +1949,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd for () { #[inline] fn partial_cmp(&self, _: &()) -> Option { Some(Equal) @@ -1913,7 +1958,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd for bool { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd for bool { #[inline] fn partial_cmp(&self, other: &bool) -> Option { Some(self.cmp(other)) @@ -1927,7 +1973,8 @@ mod impls { macro_rules! ord_impl { ($($t:ty)*) => ($( #[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: &Self) -> Option { Some(crate::intrinsics::three_way_compare(*self, *other)) @@ -1937,7 +1984,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for $t { #[inline] fn cmp(&self, other: &Self) -> Ordering { crate::intrinsics::three_way_compare(*self, *other) @@ -1947,7 +1995,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for () { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for () { #[inline] fn cmp(&self, _other: &()) -> Ordering { Equal @@ -1955,7 +2004,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for bool { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for bool { #[inline] fn cmp(&self, other: &bool) -> Ordering { // Casting to i8's and converting the difference to an Ordering generates @@ -1990,7 +2040,8 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[unstable(feature = "never_type", issue = "35121")] - impl PartialEq for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialEq for ! { #[inline] fn eq(&self, _: &!) -> bool { *self @@ -1998,10 +2049,12 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Eq for ! {} + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Eq for ! {} #[unstable(feature = "never_type", issue = "35121")] - impl PartialOrd for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd for ! { #[inline] fn partial_cmp(&self, _: &!) -> Option { *self @@ -2009,7 +2062,8 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Ord for ! { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for ! { #[inline] fn cmp(&self, _: &!) -> Ordering { *self @@ -2034,9 +2088,10 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd<&B> for &A + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd<&B> for &A where - A: PartialOrd, + A: ~const PartialOrd, { #[inline] fn partial_cmp(&self, other: &&B) -> Option { @@ -2076,9 +2131,10 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for &A + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for &A where - A: Ord, + A: ~const Ord, { #[inline] fn cmp(&self, other: &Self) -> Ordering { @@ -2086,7 +2142,8 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl Eq for &A where A: Eq {} + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Eq for &A where A: ~const Eq {} // &mut pointers @@ -2106,9 +2163,10 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialOrd<&mut B> for &mut A + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd<&mut B> for &mut A where - A: PartialOrd, + A: ~const PartialOrd, { #[inline] fn partial_cmp(&self, other: &&mut B) -> Option { @@ -2148,9 +2206,10 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl Ord for &mut A + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for &mut A where - A: Ord, + A: ~const Ord, { #[inline] fn cmp(&self, other: &Self) -> Ordering { @@ -2158,7 +2217,8 @@ mod impls { } } #[stable(feature = "rust1", since = "1.0.0")] - impl Eq for &mut A where A: Eq {} + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Eq for &mut A where A: ~const Eq {} #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 220a24caf09ee..73c9952ddfeac 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -973,17 +973,20 @@ impl const PartialEq for Infallible { } #[stable(feature = "convert_infallible", since = "1.34.0")] -impl Eq for Infallible {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for Infallible {} #[stable(feature = "convert_infallible", since = "1.34.0")] -impl PartialOrd for Infallible { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Infallible { fn partial_cmp(&self, _other: &Self) -> Option { match *self {} } } #[stable(feature = "convert_infallible", since = "1.34.0")] -impl Ord for Infallible { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for Infallible { fn cmp(&self, _other: &Self) -> crate::cmp::Ordering { match *self {} } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 106cc725fee2c..76b5875be47fd 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -71,7 +71,8 @@ use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, O /// A type for atomic ordering parameters for intrinsics. This is a separate type from /// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a /// risk of leaking that to stable code. -#[derive(Debug, ConstParamTy, PartialEq, Eq)] +#[derive(ConstParamTy, Debug)] +#[derive_const(PartialEq, Eq)] pub enum AtomicOrdering { // These values must match the compiler's `AtomicOrdering` defined in // `rustc_middle/src/ty/consts/int.rs`! diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index ba00ee17b6528..9863dbb78a09e 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1021,7 +1021,8 @@ pub auto trait Unpin {} // marker in your struct acts as if you wrapped the entire struct in an `UnsafePinned`. This type // will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead. #[stable(feature = "pin", since = "1.33.0")] -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Default, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 02bb81792931e..753e67909d630 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -151,7 +151,8 @@ use crate::ptr; /// [`MaybeUninit`]: crate::mem::MaybeUninit #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, Default, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] #[rustc_pub_transparent] pub struct ManuallyDrop { diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 782b826448a32..b835cfb2d4436 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -146,7 +146,8 @@ where /// `true`, the onus of the safety proof belongs to the programmer. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_opts"] -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(Debug, Copy)] +#[derive_const(PartialEq, Eq, Clone)] pub struct Assume { /// When `false`, [`TransmuteFrom`] is not implemented for transmutations /// that might violate the alignment requirements of references; e.g.: diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs index db7176c124318..74b1878c5b938 100644 --- a/library/core/src/num/dec2flt/decimal.rs +++ b/library/core/src/num/dec2flt/decimal.rs @@ -23,7 +23,8 @@ const INT_POW10: [u64; 16] = [ ]; /// A floating point number with up to 64 bits of mantissa and an `i64` exponent. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, Default, PartialEq, Eq)] pub struct Decimal { pub exponent: i64, pub mantissa: u64, diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index d57b1d433e51c..c0e206a047f9d 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -14,7 +14,8 @@ macro_rules! define_valid_range_type { $(#[$m:meta])* $vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal); )+) => {$( - #[derive(Clone, Copy, Eq)] + #[derive(Copy)] + #[derive_const(Clone, Eq)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start($low)] #[rustc_layout_scalar_valid_range_end($high)] @@ -67,21 +68,25 @@ macro_rules! define_valid_range_type { // by . impl StructuralPartialEq for $name {} - impl PartialEq for $name { + + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { self.as_inner() == other.as_inner() } } - impl Ord for $name { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const Ord for $name { #[inline] fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&self.as_inner(), &other.as_inner()) } } - impl PartialOrd for $name { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + impl const PartialOrd for $name { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(Ord::cmp(self, other)) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f793602de5087..a0c610f1a1c8b 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -4,7 +4,7 @@ use super::{IntErrorKind, ParseIntError}; use crate::clone::UseCloned; use crate::cmp::Ordering; use crate::hash::{Hash, Hasher}; -use crate::marker::{Freeze, StructuralPartialEq}; +use crate::marker::{Destruct, Freeze, StructuralPartialEq}; use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::str::FromStr; @@ -220,12 +220,14 @@ where impl StructuralPartialEq for NonZero where T: ZeroablePrimitive + StructuralPartialEq {} #[stable(feature = "nonzero", since = "1.28.0")] -impl Eq for NonZero where T: ZeroablePrimitive + Eq {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for NonZero where T: ZeroablePrimitive + ~const Eq {} #[stable(feature = "nonzero", since = "1.28.0")] -impl PartialOrd for NonZero +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for NonZero where - T: ZeroablePrimitive + PartialOrd, + T: ZeroablePrimitive + ~const PartialOrd, { #[inline] fn partial_cmp(&self, other: &Self) -> Option { @@ -254,9 +256,12 @@ where } #[stable(feature = "nonzero", since = "1.28.0")] -impl Ord for NonZero +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for NonZero where - T: ZeroablePrimitive + Ord, + // FIXME(const_hack): the T: ~const Destruct should be inferred from the Self: ~const Destruct. + // See https://github.com/rust-lang/rust/issues/144207 + T: ZeroablePrimitive + ~const Ord + ~const Destruct, { #[inline] fn cmp(&self, other: &Self) -> Ordering { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 26661b20c12d6..a03ec68618344 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -83,7 +83,8 @@ use crate::{convert, ops}; #[must_use] // ControlFlow should not implement PartialOrd or Ord, per RFC 3058: // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, Eq)] pub enum ControlFlow { /// Move on to the next phase of the operation as normal. #[stable(feature = "control_flow_enum_type", since = "1.55.0")] @@ -99,7 +100,8 @@ pub enum ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] -impl ops::Try for ControlFlow { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl const ops::Try for ControlFlow { type Output = C; type Residual = ControlFlow; @@ -118,9 +120,10 @@ impl ops::Try for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] +#[rustc_const_unstable(feature = "const_try", issue = "74935")] // Note: manually specifying the residual type instead of using the default to work around // https://github.com/rust-lang/rust/issues/99940 -impl ops::FromResidual> for ControlFlow { +impl const ops::FromResidual> for ControlFlow { #[inline] fn from_residual(residual: ControlFlow) -> Self { match residual { diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index c7d596d74c383..8663f360fd2d5 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -5,7 +5,8 @@ use crate::pin::Pin; /// This enum is returned from the `Coroutine::resume` method and indicates the /// possible return values of a coroutine. Currently this corresponds to either /// a suspension point (`Yielded`) or a termination point (`Complete`). -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, PartialOrd, Eq, Ord)] #[lang = "coroutine_state"] #[unstable(feature = "coroutine_trait", issue = "43122")] pub enum CoroutineState { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ed070fbd22746..e79d1f21300e9 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -585,7 +585,8 @@ use crate::{cmp, convert, hint, mem, slice}; /// The `Option` type. See [the module level documentation](self) for more. #[doc(search_unbox)] -#[derive(Copy, Eq, Debug, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Eq)] #[rustc_diagnostic_item = "Option"] #[lang = "Option"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2325,7 +2326,8 @@ impl const PartialEq for Option { // https://github.com/rust-lang/rust/issues/49892, although still // not optimal. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Option { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Option { #[inline] fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { @@ -2338,7 +2340,8 @@ impl PartialOrd for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Option { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Ord for Option { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { match (self, other) { diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bd5b4e21baa0f..7de50fede89ac 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -8,7 +8,8 @@ use crate::{cmp, fmt, hash, mem, num}; /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -240,7 +241,8 @@ impl const Default for Alignment { } #[cfg(target_pointer_width = "16")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(u16)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, @@ -262,7 +264,8 @@ enum AlignmentEnum { } #[cfg(target_pointer_width = "32")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(u32)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, @@ -300,7 +303,8 @@ enum AlignmentEnum { } #[cfg(target_pointer_width = "64")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(u64)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 7158fa0fcf069..6888f0bbc8235 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -51,7 +51,8 @@ pub use crate::ops::{ /// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum()); /// ``` #[lang = "RangeCopy"] -#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, Default, PartialEq, Eq)] #[unstable(feature = "new_range_api", issue = "125687")] pub struct Range { /// The lower bound of the range (inclusive). @@ -425,7 +426,8 @@ impl From> for RangeInclusive { /// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum()); /// ``` #[lang = "RangeFromCopy"] -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq)] #[unstable(feature = "new_range_api", issue = "125687")] pub struct RangeFrom { /// The lower bound of the range (inclusive). diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 474f86395ae0e..1bcfad13f660a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -542,7 +542,8 @@ use crate::{convert, fmt, hint}; /// /// See the [module documentation](self) for details. #[doc(search_unbox)] -#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(PartialEq, PartialOrd, Eq, Ord)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[rustc_diagnostic_item = "Result"] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 1eda8bc1bec40..963f0b74e0df6 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -4,6 +4,7 @@ use super::{from_raw_parts, memchr}; use crate::ascii; use crate::cmp::{self, BytewiseEq, Ordering}; use crate::intrinsics::compare_bytes; +use crate::marker::Destruct; use crate::num::NonZero; use crate::ops::ControlFlow; @@ -23,7 +24,8 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for [T] {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for [T] {} /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] @@ -34,7 +36,7 @@ impl Ord for [T] { } #[inline] -fn as_underlying(x: ControlFlow) -> u8 { +const fn as_underlying(x: ControlFlow) -> u8 { // SAFETY: This will only compile if `bool` and `ControlFlow` have the same // size (which isn't guaranteed but this is libcore). Because they have the same // size, it's a niched implementation, which in one byte means there can't be @@ -155,12 +157,16 @@ where } #[doc(hidden)] +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's PartialOrd 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 { fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow; @@ -183,7 +189,8 @@ impl SlicePartialOrd for A { } } -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) } @@ -199,12 +206,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, FE, FL>( 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: FE, + len_chain: FL, +) -> ControlFlow +where + FE: ~const Fn(&'l A, &'r A) -> ControlFlow + ~const Destruct, + FL: for<'a> ~const Fn(&'a usize, &'a usize) -> ControlFlow + ~const Destruct, +{ let l = cmp::min(left.len(), right.len()); // Slice to the loop iteration range to enable bound check @@ -212,8 +224,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): make this a `for i in 0..l` loop. + let mut i = 0; + while i < l { elem_chain(&lhs[i], &rhs[i])?; + i += 1; } len_chain(&left.len(), &right.len()) @@ -232,14 +247,17 @@ where } */ -impl SlicePartialOrd for A { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SlicePartialOrd for A { fn partial_compare(left: &[A], right: &[A]) -> Option { Some(SliceOrd::compare(left, right)) } } #[rustc_specialization_trait] -trait AlwaysApplicableOrd: SliceOrd + Ord {} +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +trait AlwaysApplicableOrd: ~const SliceOrd + ~const Ord {} macro_rules! always_applicable_ord { ($([$($p:tt)*] $t:ty,)*) => { @@ -258,6 +276,8 @@ always_applicable_ord! { } #[doc(hidden)] +#[const_trait] +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's Ord trait SliceOrd: Sized { fn compare(left: &[Self], right: &[Self]) -> Ordering; @@ -283,17 +303,24 @@ impl SliceOrd for A { /// * For every `x` and `y` of this type, `Ord(x, y)` must return the same /// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. #[rustc_specialization_trait] -unsafe trait UnsignedBytewiseOrd: Ord {} +#[const_trait] +unsafe trait UnsignedBytewiseOrd: ~const Ord {} -unsafe impl UnsignedBytewiseOrd for bool {} -unsafe impl UnsignedBytewiseOrd for u8 {} -unsafe impl UnsignedBytewiseOrd for NonZero {} -unsafe impl UnsignedBytewiseOrd for Option> {} -unsafe impl UnsignedBytewiseOrd for ascii::Char {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +unsafe impl const UnsignedBytewiseOrd for bool {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +unsafe impl const UnsignedBytewiseOrd for u8 {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +unsafe impl const UnsignedBytewiseOrd for NonZero {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +unsafe impl const UnsignedBytewiseOrd for Option> {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +unsafe impl const UnsignedBytewiseOrd for ascii::Char {} // `compare_bytes` compares a sequence of unsigned bytes lexicographically, so // use it if the requirements for `UnsignedBytewiseOrd` are fulfilled. -impl SliceOrd for A { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SliceOrd for A { #[inline] fn compare(left: &[Self], right: &[Self]) -> Ordering { // Since the length of a slice is always less than or equal to @@ -318,7 +345,9 @@ impl SliceOrd for A { } // Don't generate our own chaining loops for `memcmp`-able things either. -impl SliceChain for A { + +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const SliceChain for A { #[inline] fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow { match SliceOrd::compare(left, right) { diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 8d4210c80827d..aef72eab71fcf 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -67,7 +67,8 @@ impl [u8] { /// assert_eq!(b"\xF1\x80", chunk.invalid()); /// ``` #[stable(feature = "utf8_chunks", since = "1.79.0")] -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug)] +#[derive_const(PartialEq, Eq)] pub struct Utf8Chunk<'a> { valid: &'a str, invalid: &'a [u8], diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index e116b13838323..3e04170cdadf7 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -170,7 +170,8 @@ pub trait Pattern: Sized { /// Result of calling [`Pattern::as_utf8_pattern()`]. /// Can be used for inspecting the contents of a [`Pattern`] in cases /// where the underlying representation can be represented as UTF-8. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[derive(Copy, Debug)] +#[derive_const(Clone, Eq, PartialEq)] pub enum Utf8Pattern<'a> { /// Type returned by String and str types. StringPattern(&'a [u8]), diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 1597d1c1fa868..31319964033a7 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -32,7 +32,8 @@ impl const PartialEq for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for str {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const Eq for str {} /// Implements comparison operations on strings. /// diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 70c02ead35848..b635f16f0dbf2 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -433,7 +433,8 @@ unsafe impl Sync for AtomicPtr {} /// /// [nomicon]: ../../../nomicon/atomics.html #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, Eq, PartialEq)] #[non_exhaustive] #[rustc_diagnostic_item = "Ordering"] pub enum Ordering { diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 0fb5c0bac7562..04cdc8f53ccf8 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -76,7 +76,8 @@ const DAYS_PER_WEEK: u64 = 7; /// compatibility, you may wish to format `Duration` objects yourself or use a /// crate to do so. #[stable(feature = "duration", since = "1.3.0")] -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Hash)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] #[rustc_diagnostic_item = "Duration"] pub struct Duration { secs: u64, @@ -1456,7 +1457,8 @@ impl fmt::Display for TryFromFloatSecsError { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] enum TryFromFloatSecsErrorKind { // Value is negative. Negative, diff --git a/library/coretests/tests/cmp.rs b/library/coretests/tests/cmp.rs index 6c4e2146f9148..55e35a4a7250e 100644 --- a/library/coretests/tests/cmp.rs +++ b/library/coretests/tests/cmp.rs @@ -215,19 +215,18 @@ fn cmp_default() { assert_eq!(Fool(false), Fool(true)); } -/* FIXME(#110395) mod const_cmp { use super::*; struct S(i32); - impl PartialEq for S { + impl const PartialEq for S { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } - impl PartialOrd for S { + impl const PartialOrd for S { fn partial_cmp(&self, other: &Self) -> Option { let ret = match (self.0, other.0) { (a, b) if a > b => Ordering::Greater, @@ -247,4 +246,3 @@ mod const_cmp { const _: () = assert!(S(0) < S(1)); const _: () = assert!(S(1) > S(0)); } -*/ diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 0a9c0c61c9584..b885229747d35 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,6 +15,7 @@ #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_max_len)] #![feature(clone_to_uninit)] +#![feature(const_cmp)] #![feature(const_deref)] #![feature(const_destruct)] #![feature(const_eval_select)] diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index 8c21f7b1a5a90..254b875228170 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -9,8 +9,7 @@ fn main() { assert!(TypeId::of::() == TypeId::of::()); assert!(TypeId::of::<()>() != TypeId::of::()); let _a = TypeId::of::() < TypeId::of::(); - //~^ ERROR: cannot call non-const operator in constants - // can't assert `_a` because it is not deterministic - // FIXME(const_trait_impl) make it pass + //~^ ERROR: the trait bound `TypeId: const PartialOrd` is not satisfied + // FIXME(const_trait_impl) make it pass; requires const comparison of pointers (#53020) } } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 05b94caef79e6..62a1677c0d930 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,13 +1,9 @@ -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `TypeId: const PartialOrd` is not satisfied --> $DIR/const_cmp_type_id.rs:11:18 | LL | let _a = TypeId::of::() < TypeId::of::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs index da28d9a47c31e..c89aaa62d9922 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-trait.rs @@ -1,7 +1,5 @@ +//@ check-pass //@ compile-flags: -Znext-solver -//@ known-bug: #110395 - -// Broken until `(): const PartialEq` #![allow(incomplete_features)] #![feature(const_trait_impl, const_cmp, const_destruct)] diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr deleted file mode 100644 index cbb68d8c9839e..0000000000000 --- a/tests/ui/traits/const-traits/const-impl-trait.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the trait bound `(): const PartialEq` is not satisfied - --> $DIR/const-impl-trait.rs:34:17 - | -LL | assert!(cmp(&())); - | --- ^^^ - | | - | required by a bound introduced by this call - | -note: required by a bound in `cmp` - --> $DIR/const-impl-trait.rs:11:23 - | -LL | const fn cmp(a: &impl [const] PartialEq) -> bool { - | ^^^^^^^^^^^^^^^^^ required by this bound in `cmp` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.rs b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs index 1a3012de06f81..78c25ccd6e598 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs @@ -1,5 +1,4 @@ -//@ known-bug: #110395 - +//@ check-pass #![feature(const_trait_impl, const_default, const_cmp, derive_const)] pub struct A; diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr deleted file mode 100644 index 4ea11a0c7ed91..0000000000000 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0277]: the trait bound `(): [const] PartialEq` is not satisfied - --> $DIR/derive-const-use.rs:16:14 - | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`.