diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index cd5fd77f86597..4d5e342d5fde4 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. @@ -545,7 +546,8 @@ pub type LayoutErr = LayoutError; /// do not satisfy its documented constraints. #[stable(feature = "alloc_layout_error", since = "1.50.0")] #[non_exhaustive] -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub struct LayoutError; #[stable(feature = "alloc_layout", since = "1.28.0")] diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index c2c7ccf0daa23..ec79a657e58e2 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -132,9 +132,8 @@ where #[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 { +const trait SpecArrayEq: Sized { fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index d713e575b58d3..590ccef4f55e9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -403,7 +403,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[..]) @@ -428,7 +429,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/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/char/mod.rs b/library/core/src/char/mod.rs index 82a3f6f916be3..8d4e587bc0e71 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(Debug, Copy)] +#[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/clone.rs b/library/core/src/clone.rs index 7f2a40f753fa6..06d2c93cc698f 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -575,7 +575,8 @@ mod impls { ($($t:ty)*) => { $( #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for $t { + #[rustc_const_unstable(feature = "const_clone", issue = "142757")] + impl const Clone for $t { #[inline(always)] fn clone(&self) -> Self { *self @@ -593,7 +594,8 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Clone for ! { + #[rustc_const_unstable(feature = "const_clone", issue = "142757")] + impl const Clone for ! { #[inline] fn clone(&self) -> Self { *self @@ -601,7 +603,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *const T { + #[rustc_const_unstable(feature = "const_clone", issue = "142757")] + impl const Clone for *const T { #[inline(always)] fn clone(&self) -> Self { *self @@ -609,7 +612,8 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for *mut T { + #[rustc_const_unstable(feature = "const_clone", issue = "142757")] + impl const Clone for *mut T { #[inline(always)] fn clone(&self) -> Self { *self @@ -618,7 +622,8 @@ mod impls { /// Shared references can be cloned, but mutable references *cannot*! #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for &T { + #[rustc_const_unstable(feature = "const_clone", issue = "142757")] + impl const Clone for &T { #[inline(always)] #[rustc_diagnostic_item = "noop_method_clone"] fn clone(&self) -> Self { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index d0b53e3a237f6..7828e3ca02cd3 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] @@ -669,7 +670,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()) @@ -677,7 +679,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/fmt/mod.rs b/library/core/src/fmt/mod.rs index b6de892530892..a3cea11e7b4cc 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -21,7 +21,8 @@ mod rt; #[stable(feature = "fmt_flags_align", since = "1.28.0")] #[rustc_diagnostic_item = "Alignment"] /// Possible alignments returned by `Formatter::align` -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub enum Alignment { #[stable(feature = "fmt_flags_align", since = "1.28.0")] /// Indication that contents should be left-aligned. @@ -103,7 +104,8 @@ pub type Result = result::Result<(), Error>; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct Error; /// A trait for writing or formatting into Unicode-accepting buffers or streams. @@ -255,7 +257,8 @@ impl Write for &mut W { } /// The signedness of a [`Formatter`] (or of a [`FormattingOptions`]). -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub enum Sign { /// Represents the `+` flag. @@ -266,7 +269,8 @@ pub enum Sign { /// Specifies whether the [`Debug`] trait should use lower-/upper-case /// hexadecimal or normal integers. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub enum DebugAsHex { /// Use lower-case hexadecimal integers for the `Debug` trait (like [the `x?` type](../../std/fmt/index.html#formatting-traits)). @@ -279,7 +283,8 @@ pub enum DebugAsHex { /// /// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait. /// It is mainly used to construct `Formatter` instances. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub struct FormattingOptions { /// Flags, with the following bit fields: diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index bffffbc29c1eb..5dbbcfe81bac2 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(Debug, ConstParamTy)] +#[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 1c100312a9a33..2d9091bd387c5 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -828,24 +828,28 @@ impl Hash for PhantomData { } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialEq for PhantomData { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::PartialEq for PhantomData { fn eq(&self, _other: &PhantomData) -> bool { true } } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Eq for PhantomData {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::Eq for PhantomData {} #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::PartialOrd for PhantomData { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::PartialOrd for PhantomData { fn partial_cmp(&self, _other: &PhantomData) -> Option { Option::Some(cmp::Ordering::Equal) } } #[stable(feature = "rust1", since = "1.0.0")] -impl cmp::Ord for PhantomData { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::Ord for PhantomData { fn cmp(&self, _other: &PhantomData) -> cmp::Ordering { cmp::Ordering::Equal } @@ -1021,7 +1025,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(Debug, Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord, Default)] 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 8868f05f1b98f..715844796bfaa 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, PartialEq, Eq, PartialOrd, Ord, Default)] #[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 f36cb8cddb837..cbfe21715168a 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -147,7 +147,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(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] 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/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 9779fb8fe4d5e..39e5948b5b7ec 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -26,7 +26,8 @@ use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; /// ``` #[rustc_diagnostic_item = "IpAddr"] #[stable(feature = "ip_addr", since = "1.7.0")] -#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum IpAddr { /// An IPv4 address. #[stable(feature = "ip_addr", since = "1.7.0")] @@ -68,7 +69,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 +163,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], @@ -1161,7 +1164,8 @@ impl fmt::Debug for Ipv4Addr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialEq for IpAddr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for IpAddr { #[inline] fn eq(&self, other: &Ipv4Addr) -> bool { match self { @@ -1172,7 +1176,8 @@ impl PartialEq for IpAddr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialEq for Ipv4Addr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for Ipv4Addr { #[inline] fn eq(&self, other: &IpAddr) -> bool { match other { @@ -1183,7 +1188,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)) @@ -1191,7 +1197,8 @@ impl PartialOrd for Ipv4Addr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialOrd for IpAddr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for IpAddr { #[inline] fn partial_cmp(&self, other: &Ipv4Addr) -> Option { match self { @@ -1202,7 +1209,8 @@ impl PartialOrd for IpAddr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialOrd for Ipv4Addr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Ipv4Addr { #[inline] fn partial_cmp(&self, other: &IpAddr) -> Option { match other { @@ -1213,7 +1221,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) @@ -2155,7 +2164,8 @@ impl fmt::Debug for Ipv6Addr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialEq for Ipv6Addr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for Ipv6Addr { #[inline] fn eq(&self, other: &IpAddr) -> bool { match other { @@ -2166,7 +2176,8 @@ impl PartialEq for Ipv6Addr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialEq for IpAddr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialEq for IpAddr { #[inline] fn eq(&self, other: &Ipv6Addr) -> bool { match self { @@ -2177,7 +2188,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)) @@ -2185,7 +2197,8 @@ impl PartialOrd for Ipv6Addr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialOrd for IpAddr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for IpAddr { #[inline] fn partial_cmp(&self, other: &Ipv6Addr) -> Option { match self { @@ -2196,7 +2209,8 @@ impl PartialOrd for IpAddr { } #[stable(feature = "ip_cmp", since = "1.16.0")] -impl PartialOrd for Ipv6Addr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const PartialOrd for Ipv6Addr { #[inline] fn partial_cmp(&self, other: &IpAddr) -> Option { match other { @@ -2207,7 +2221,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()) @@ -2223,6 +2238,7 @@ impl const From for u128 { ip.to_bits() } } + #[stable(feature = "i128", since = "1.26.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From for Ipv6Addr { diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index ccc53c156d3a1..4b4a8f0c529ea 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -28,7 +28,8 @@ use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// assert_eq!(socket.port(), 8080); /// assert_eq!(socket.is_ipv4(), true); /// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub enum SocketAddr { /// An IPv4 socket address. @@ -76,7 +77,8 @@ pub enum SocketAddr { /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// assert_eq!(socket.port(), 8080); /// ``` -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV4 { ip: Ipv4Addr, @@ -142,7 +144,8 @@ pub struct SocketAddrV4 { /// with_scope.set_scope_id(3); /// assert_eq!("[2001:db8::1%3]:8080".parse(), Ok(with_scope)); /// ``` -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV6 { ip: Ipv6Addr, diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 8a353dc0fbe99..269b4ad7fac64 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -6,7 +6,8 @@ use crate::fmt; /// The error type returned when a checked integral type conversion fails. #[stable(feature = "try_from", since = "1.34.0")] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy)] +#[derive_const(Clone, PartialEq, Eq)] pub struct TryFromIntError(pub(crate) ()); #[stable(feature = "try_from", since = "1.34.0")] @@ -60,7 +61,8 @@ impl const From for TryFromIntError { /// println!("Failed conversion to i32: {e}"); /// } /// ``` -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseIntError { pub(super) kind: IntErrorKind, @@ -78,7 +80,8 @@ pub struct ParseIntError { /// # } /// ``` #[stable(feature = "int_error_matching", since = "1.55.0")] -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +#[derive(Debug, Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { /// Value being parsed is empty. diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 66c892aadd083..c5323c9d0421a 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1196,7 +1196,8 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i128; let mut right = other.to_bits() as i128; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 81220065e72a6..77b73b6348924 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1175,7 +1175,8 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i16; let mut right = other.to_bits() as i16; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index cefcf1d1fe2fc..da0ba7fe1db56 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1353,9 +1353,10 @@ impl f32 { /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[must_use] #[inline] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i32; let mut right = other.to_bits() as i32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 9dd1141e70331..c93056e310635 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1351,9 +1351,10 @@ impl f64 { /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[must_use] #[inline] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i64; let mut right = other.to_bits() as i64; diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index 610d9d8cf92e0..5c856eaf46506 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,24 @@ 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)) @@ -112,7 +116,8 @@ impl Nanoseconds { pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) }; } -impl Default for Nanoseconds { +#[rustc_const_unstable(feature = "const_default", issue = "143894")] +impl const Default for Nanoseconds { #[inline] fn default() -> Self { Self::ZERO diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index 365a82a57e0b9..984b7b7c9fcf9 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -32,7 +32,8 @@ use crate::ops::{ /// assert_eq!(u32::MAX, (max + one).0); /// ``` #[stable(feature = "saturating_int_impl", since = "1.74.0")] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord, Default)] #[repr(transparent)] #[rustc_diagnostic_item = "Saturating"] pub struct Saturating(#[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T); diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index 881fe615f800f..2db7a8caaadb1 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -37,7 +37,8 @@ use crate::ops::{ /// /// `Wrapping` is guaranteed to have the same layout and ABI as `T`. #[stable(feature = "rust1", since = "1.0.0")] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord, Default)] #[repr(transparent)] #[rustc_diagnostic_item = "Wrapping"] pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index c7d596d74c383..f8f214499461c 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, Eq, PartialOrd, Ord)] #[lang = "coroutine_state"] #[unstable(feature = "coroutine_trait", issue = "43122")] pub enum CoroutineState { diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 507fa9460bea6..c3335ccecc830 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -9,7 +9,8 @@ use crate::ub_checks; /// /// (Normal `Range` code needs to handle degenerate ranges like `10..0`, /// which takes extra checks compared to only handling the canonical form.) -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub(crate) struct IndexRange { start: usize, end: usize, diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 58a9431bd845d..e2b15673f1359 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -38,7 +38,8 @@ use crate::hash::Hash; /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeFull"] #[doc(alias = "..")] -#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, Default)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFull; @@ -75,7 +76,8 @@ impl fmt::Debug for RangeFull { /// ``` #[lang = "Range"] #[doc(alias = "..")] -#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Hash)] // not Copy -- see #27186 +#[derive_const(Clone, PartialEq, Eq, Default)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -184,7 +186,8 @@ impl> Range { /// ``` #[lang = "RangeFrom"] #[doc(alias = "..")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Hash)] // not Copy -- see #27186 +#[derive_const(Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -266,7 +269,8 @@ impl> RangeFrom { /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeTo"] #[doc(alias = "..")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { /// The upper bound of the range (exclusive). @@ -340,7 +344,8 @@ impl> RangeTo { /// ``` #[lang = "RangeInclusive"] #[doc(alias = "..=")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Hash)] // not Copy -- see #27186 +#[derive_const(Clone, PartialEq, Eq)] #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { // Note that the fields here are not public to allow changing the @@ -587,7 +592,8 @@ impl> RangeInclusive { /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeToInclusive"] #[doc(alias = "..=")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq)] #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) @@ -668,7 +674,8 @@ impl> RangeToInclusive { /// /// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range #[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, Eq)] pub enum Bound { /// An inclusive bound. #[stable(feature = "collections_bound", since = "1.17.0")] diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 7a68d393906cb..fd6e45475ee27 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,26 @@ 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)) + 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/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bc7d3a1de7151..de911f4a6cdf9 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -10,7 +10,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); @@ -211,7 +212,8 @@ impl const From for usize { } #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl cmp::Ord for Alignment { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::Ord for Alignment { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { self.as_nonzero().get().cmp(&other.as_nonzero().get()) @@ -219,7 +221,8 @@ impl cmp::Ord for Alignment { } #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl cmp::PartialOrd for Alignment { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +impl const cmp::PartialOrd for Alignment { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -244,7 +247,8 @@ impl const Default for Alignment { } #[cfg(target_pointer_width = "16")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, @@ -266,7 +270,8 @@ enum AlignmentEnum { } #[cfg(target_pointer_width = "32")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, @@ -304,7 +309,8 @@ enum AlignmentEnum { } #[cfg(target_pointer_width = "64")] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy)] +#[derive_const(Clone, PartialEq, Eq)] #[repr(usize)] enum AlignmentEnum { _Align1Shl0 = 1 << 0, diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 103630aba0f79..7dec1ec81b783 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,10 @@ fn chaining_impl<'l, 'r, A: PartialOrd, B, C>( let lhs = &left[..l]; let rhs = &right[..l]; - for i in 0..l { + let mut i = 0; + while i < l { elem_chain(&lhs[i], &rhs[i])?; + i += 1; } len_chain(&left.len(), &right.len()) @@ -244,13 +266,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 +282,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 +371,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/error.rs b/library/core/src/str/error.rs index 1677c849ae4bf..974c0513a8a11 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -42,7 +42,8 @@ use crate::fmt; /// } /// } /// ``` -#[derive(Copy, Eq, PartialEq, Clone, Debug)] +#[derive(Copy, Debug)] +#[derive_const(Clone, Eq, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Utf8Error { pub(super) valid_up_to: usize, @@ -129,7 +130,8 @@ impl Error for Utf8Error {} /// An error returned when parsing a `bool` using [`from_str`] fails /// /// [`from_str`]: super::FromStr::from_str -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, PartialEq, Eq)] #[non_exhaustive] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseBoolError; diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 8d4210c80827d..24cbd1e1977f8 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(Debug)] +#[derive_const(Clone, 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..581654f272190 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, PartialEq, Eq)] pub enum Utf8Pattern<'a> { /// Type returned by String and str types. StringPattern(&'a [u8]), @@ -181,7 +182,8 @@ pub enum Utf8Pattern<'a> { // Searcher /// Result of calling [`Searcher::next()`] or [`ReverseSearcher::next_back()`]. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[derive(Copy, Debug)] +#[derive_const(Clone, PartialEq, Eq)] pub enum SearchStep { /// Expresses that a match of the pattern has been found at /// `haystack[a..b]`. 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)) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1b4a54b1b7a78..c180bfc495c4a 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, PartialEq, Eq)] #[non_exhaustive] #[rustc_diagnostic_item = "Ordering"] pub enum Ordering { diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 380abac0ae95f..f0c810dcb1f72 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -8,7 +8,8 @@ use crate::ops::{self, ControlFlow}; /// /// This is returned by [`Future::poll`](core::future::Future::poll). #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord)] #[lang = "Poll"] #[stable(feature = "futures_api", since = "1.36.0")] pub enum Poll { diff --git a/library/core/src/time.rs b/library/core/src/time.rs index d205bc376f125..13706fa7e5001 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(Copy, Hash)] +#[derive_const(Clone, PartialEq, Eq, PartialOrd, Ord, Default)] #[rustc_diagnostic_item = "Duration"] pub struct Duration { secs: u64, @@ -1475,7 +1476,8 @@ impl fmt::Debug for Duration { /// println!("Failed conversion to Duration: {e}"); /// } /// ``` -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone)] +#[derive_const(PartialEq, Eq)] #[stable(feature = "duration_checked_float", since = "1.66.0")] pub struct TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind, @@ -1496,7 +1498,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/core/src/wtf8.rs b/library/core/src/wtf8.rs index de0dfa560a3f3..8b4bb27207ea4 100644 --- a/library/core/src/wtf8.rs +++ b/library/core/src/wtf8.rs @@ -33,7 +33,8 @@ use crate::{ops, slice, str}; /// Compares with the `char` type, /// which represents a Unicode scalar value: /// a code point that is not a surrogate (U+D800 to U+DFFF). -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] +#[derive(Clone, Copy)] +#[derive_const(Eq, PartialEq, Ord, PartialOrd)] #[doc(hidden)] pub struct CodePoint(CodePointInner); @@ -123,7 +124,7 @@ impl CodePoint { /// /// Similar to `&str`, but can additionally contain surrogate code points /// if they’re not in a surrogate pair. -#[derive(Eq, Ord, PartialEq, PartialOrd)] +#[derive_const(Eq, Ord, PartialEq, PartialOrd)] #[repr(transparent)] #[rustc_has_incoherent_inherent_impls] #[doc(hidden)] diff --git a/tests/ui/consts/const-total-cmp.rs b/tests/ui/consts/const-total-cmp.rs new file mode 100644 index 0000000000000..bb810c945b530 --- /dev/null +++ b/tests/ui/consts/const-total-cmp.rs @@ -0,0 +1,113 @@ +//@ run-pass + +#![feature(const_cmp, f16, f128)] + +use std::cmp::Ordering; + +fn main() { + // Test f32::total_cmp in const context + const F32_EQUAL: Ordering = (1.0_f32).total_cmp(&1.0_f32); + assert_eq!(F32_EQUAL, Ordering::Equal); + + const F32_LESS: Ordering = (1.0_f32).total_cmp(&2.0_f32); + assert_eq!(F32_LESS, Ordering::Less); + + const F32_GREATER: Ordering = (2.0_f32).total_cmp(&1.0_f32); + assert_eq!(F32_GREATER, Ordering::Greater); + + // Test special values for f32 + const F32_NEG_ZERO_VS_POS_ZERO: Ordering = (-0.0_f32).total_cmp(&0.0_f32); + assert_eq!(F32_NEG_ZERO_VS_POS_ZERO, Ordering::Less); + + const F32_NAN_VS_FINITE: Ordering = f32::NAN.total_cmp(&1.0_f32); + assert_eq!(F32_NAN_VS_FINITE, Ordering::Greater); + + const F32_INFINITY_VS_FINITE: Ordering = f32::INFINITY.total_cmp(&1.0_f32); + assert_eq!(F32_INFINITY_VS_FINITE, Ordering::Greater); + + const F32_NEG_INFINITY_VS_FINITE: Ordering = f32::NEG_INFINITY.total_cmp(&1.0_f32); + assert_eq!(F32_NEG_INFINITY_VS_FINITE, Ordering::Less); + + // Test f64::total_cmp in const context + const F64_EQUAL: Ordering = (1.0_f64).total_cmp(&1.0_f64); + assert_eq!(F64_EQUAL, Ordering::Equal); + + const F64_LESS: Ordering = (1.0_f64).total_cmp(&2.0_f64); + assert_eq!(F64_LESS, Ordering::Less); + + const F64_GREATER: Ordering = (2.0_f64).total_cmp(&1.0_f64); + assert_eq!(F64_GREATER, Ordering::Greater); + + // Test special values for f64 + const F64_NEG_ZERO_VS_POS_ZERO: Ordering = (-0.0_f64).total_cmp(&0.0_f64); + assert_eq!(F64_NEG_ZERO_VS_POS_ZERO, Ordering::Less); + + const F64_NAN_VS_FINITE: Ordering = f64::NAN.total_cmp(&1.0_f64); + assert_eq!(F64_NAN_VS_FINITE, Ordering::Greater); + + const F64_INFINITY_VS_FINITE: Ordering = f64::INFINITY.total_cmp(&1.0_f64); + assert_eq!(F64_INFINITY_VS_FINITE, Ordering::Greater); + + const F64_NEG_INFINITY_VS_FINITE: Ordering = f64::NEG_INFINITY.total_cmp(&1.0_f64); + assert_eq!(F64_NEG_INFINITY_VS_FINITE, Ordering::Less); + + // Test edge cases: comparing NaNs with each other + const F32_NAN_VS_NAN: Ordering = f32::NAN.total_cmp(&f32::NAN); + assert_eq!(F32_NAN_VS_NAN, Ordering::Equal); + + const F64_NAN_VS_NAN: Ordering = f64::NAN.total_cmp(&f64::NAN); + assert_eq!(F64_NAN_VS_NAN, Ordering::Equal); + + // Test subnormal numbers + const F32_SUBNORMAL_CMP: Ordering = f32::MIN_POSITIVE.total_cmp(&(f32::MIN_POSITIVE / 2.0)); + assert_eq!(F32_SUBNORMAL_CMP, Ordering::Greater); + + const F64_SUBNORMAL_CMP: Ordering = f64::MIN_POSITIVE.total_cmp(&(f64::MIN_POSITIVE / 2.0)); + assert_eq!(F64_SUBNORMAL_CMP, Ordering::Greater); + + // Test f16::total_cmp in const context + const F16_EQUAL: Ordering = (1.0_f16).total_cmp(&1.0_f16); + assert_eq!(F16_EQUAL, Ordering::Equal); + + const F16_LESS: Ordering = (1.0_f16).total_cmp(&2.0_f16); + assert_eq!(F16_LESS, Ordering::Less); + + const F16_GREATER: Ordering = (2.0_f16).total_cmp(&1.0_f16); + assert_eq!(F16_GREATER, Ordering::Greater); + + // Test special values for f16 + const F16_NEG_ZERO_VS_POS_ZERO: Ordering = (-0.0_f16).total_cmp(&0.0_f16); + assert_eq!(F16_NEG_ZERO_VS_POS_ZERO, Ordering::Less); + + const F16_NAN_VS_FINITE: Ordering = f16::NAN.total_cmp(&1.0_f16); + assert_eq!(F16_NAN_VS_FINITE, Ordering::Greater); + + const F16_INFINITY_VS_FINITE: Ordering = f16::INFINITY.total_cmp(&1.0_f16); + assert_eq!(F16_INFINITY_VS_FINITE, Ordering::Greater); + + const F16_NAN_VS_NAN: Ordering = f16::NAN.total_cmp(&f16::NAN); + assert_eq!(F16_NAN_VS_NAN, Ordering::Equal); + + // Test f128::total_cmp in const context + const F128_EQUAL: Ordering = (1.0_f128).total_cmp(&1.0_f128); + assert_eq!(F128_EQUAL, Ordering::Equal); + + const F128_LESS: Ordering = (1.0_f128).total_cmp(&2.0_f128); + assert_eq!(F128_LESS, Ordering::Less); + + const F128_GREATER: Ordering = (2.0_f128).total_cmp(&1.0_f128); + assert_eq!(F128_GREATER, Ordering::Greater); + + // Test special values for f128 + const F128_NEG_ZERO_VS_POS_ZERO: Ordering = (-0.0_f128).total_cmp(&0.0_f128); + assert_eq!(F128_NEG_ZERO_VS_POS_ZERO, Ordering::Less); + + const F128_NAN_VS_FINITE: Ordering = f128::NAN.total_cmp(&1.0_f128); + assert_eq!(F128_NAN_VS_FINITE, Ordering::Greater); + + const F128_INFINITY_VS_FINITE: Ordering = f128::INFINITY.total_cmp(&1.0_f128); + assert_eq!(F128_INFINITY_VS_FINITE, Ordering::Greater); + + const F128_NAN_VS_NAN: Ordering = f128::NAN.total_cmp(&f128::NAN); + assert_eq!(F128_NAN_VS_NAN, Ordering::Equal); +}