Skip to content

Commit f4fd997

Browse files
committed
constify the Eq, PartialOrd and Ord traits
Also constify the impls of basic types. One potentially controversial part of this change is making Eq, a marker trait, const. I chose to do this ease user adoption. Otherwise, code which already has an Eq bound and uses it to proxy a PartialEq bound would need to add a separate bound. This would cause a litering of bounds in downstream types. I also chose to inline default_chaining_impl() since this avoids making the core comparison constness depend on const closures. The code duplication is minimal.
1 parent 6be2340 commit f4fd997

File tree

1 file changed

+76
-48
lines changed

1 file changed

+76
-48
lines changed

library/core/src/cmp.rs

Lines changed: 76 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(crate) use bytewise::BytewiseEq;
3131
use self::Ordering::*;
3232
use crate::marker::PointeeSized;
3333
use crate::ops::ControlFlow;
34+
use crate::marker::Destruct;
3435

3536
/// Trait for comparisons using the equality operator.
3637
///
@@ -335,7 +336,8 @@ pub macro PartialEq($item:item) {
335336
#[doc(alias = "!=")]
336337
#[stable(feature = "rust1", since = "1.0.0")]
337338
#[rustc_diagnostic_item = "Eq"]
338-
pub trait Eq: PartialEq<Self> + PointeeSized {
339+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
340+
pub const trait Eq: [const] PartialEq<Self> + PointeeSized {
339341
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
340342
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
341343
// without using a method on this trait is nearly impossible.
@@ -958,7 +960,8 @@ impl<T: Clone> Clone for Reverse<T> {
958960
#[doc(alias = ">=")]
959961
#[stable(feature = "rust1", since = "1.0.0")]
960962
#[rustc_diagnostic_item = "Ord"]
961-
pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
963+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
964+
pub const trait Ord: [const] Eq + [const] PartialOrd<Self> + PointeeSized {
962965
/// This method returns an [`Ordering`] between `self` and `other`.
963966
///
964967
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
@@ -1012,7 +1015,7 @@ pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
10121015
#[rustc_diagnostic_item = "cmp_ord_max"]
10131016
fn max(self, other: Self) -> Self
10141017
where
1015-
Self: Sized,
1018+
Self: Sized + [const] Destruct,
10161019
{
10171020
if other < self { self } else { other }
10181021
}
@@ -1051,7 +1054,7 @@ pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
10511054
#[rustc_diagnostic_item = "cmp_ord_min"]
10521055
fn min(self, other: Self) -> Self
10531056
where
1054-
Self: Sized,
1057+
Self: Sized + [const] Destruct,
10551058
{
10561059
if other < self { other } else { self }
10571060
}
@@ -1077,7 +1080,7 @@ pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
10771080
#[stable(feature = "clamp", since = "1.50.0")]
10781081
fn clamp(self, min: Self, max: Self) -> Self
10791082
where
1080-
Self: Sized,
1083+
Self: Sized + [const] Destruct,
10811084
{
10821085
assert!(min <= max);
10831086
if self < min {
@@ -1342,7 +1345,8 @@ pub macro Ord($item:item) {
13421345
)]
13431346
#[rustc_diagnostic_item = "PartialOrd"]
13441347
#[allow(multiple_supertrait_upcastable)] // FIXME(sized_hierarchy): remove this
1345-
pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
1348+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1349+
pub const trait PartialOrd<Rhs: PointeeSized = Self>: [const] PartialEq<Rhs> + PointeeSized {
13461350
/// This method returns an ordering between `self` and `other` values if one exists.
13471351
///
13481352
/// # Examples
@@ -1454,50 +1458,59 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
14541458
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
14551459
#[doc(hidden)]
14561460
fn __chaining_lt(&self, other: &Rhs) -> ControlFlow<bool> {
1457-
default_chaining_impl(self, other, Ordering::is_lt)
1461+
// It's important that this only call `partial_cmp` once, not call `eq` then
1462+
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1463+
// `String`, for example, or similarly for other data structures (#108157).
1464+
match self.partial_cmp(other) {
1465+
Some(Equal) => ControlFlow::Continue(()),
1466+
Some(c) => ControlFlow::Break(c.is_lt()),
1467+
None => ControlFlow::Break(false),
1468+
}
14581469
}
14591470

14601471
/// Same as `__chaining_lt`, but for `<=` instead of `<`.
14611472
#[inline]
14621473
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
14631474
#[doc(hidden)]
14641475
fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> {
1465-
default_chaining_impl(self, other, Ordering::is_le)
1476+
// It's important that this only call `partial_cmp` once, not call `eq` then
1477+
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1478+
// `String`, for example, or similarly for other data structures (#108157).
1479+
match self.partial_cmp(other) {
1480+
Some(Equal) => ControlFlow::Continue(()),
1481+
Some(c) => ControlFlow::Break(c.is_le()),
1482+
None => ControlFlow::Break(false),
1483+
}
14661484
}
14671485

14681486
/// Same as `__chaining_lt`, but for `>` instead of `<`.
14691487
#[inline]
14701488
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
14711489
#[doc(hidden)]
14721490
fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> {
1473-
default_chaining_impl(self, other, Ordering::is_gt)
1491+
// It's important that this only call `partial_cmp` once, not call `eq` then
1492+
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1493+
// `String`, for example, or similarly for other data structures (#108157).
1494+
match self.partial_cmp(other) {
1495+
Some(Equal) => ControlFlow::Continue(()),
1496+
Some(c) => ControlFlow::Break(c.is_gt()),
1497+
None => ControlFlow::Break(false),
1498+
}
14741499
}
14751500

14761501
/// Same as `__chaining_lt`, but for `>=` instead of `<`.
14771502
#[inline]
14781503
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
14791504
#[doc(hidden)]
14801505
fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {
1481-
default_chaining_impl(self, other, Ordering::is_ge)
1482-
}
1483-
}
1484-
1485-
fn default_chaining_impl<T, U>(
1486-
lhs: &T,
1487-
rhs: &U,
1488-
p: impl FnOnce(Ordering) -> bool,
1489-
) -> ControlFlow<bool>
1490-
where
1491-
T: PartialOrd<U> + PointeeSized,
1492-
U: PointeeSized,
1493-
{
1494-
// It's important that this only call `partial_cmp` once, not call `eq` then
1495-
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1496-
// `String`, for example, or similarly for other data structures (#108157).
1497-
match <T as PartialOrd<U>>::partial_cmp(lhs, rhs) {
1498-
Some(Equal) => ControlFlow::Continue(()),
1499-
Some(c) => ControlFlow::Break(p(c)),
1500-
None => ControlFlow::Break(false),
1506+
// It's important that this only call `partial_cmp` once, not call `eq` then
1507+
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1508+
// `String`, for example, or similarly for other data structures (#108157).
1509+
match self.partial_cmp(other) {
1510+
Some(Equal) => ControlFlow::Continue(()),
1511+
Some(c) => ControlFlow::Break(c.is_ge()),
1512+
None => ControlFlow::Break(false),
1513+
}
15011514
}
15021515
}
15031516

@@ -1831,7 +1844,8 @@ mod impls {
18311844
}
18321845

18331846
#[stable(feature = "rust1", since = "1.0.0")]
1834-
impl PartialEq for () {
1847+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1848+
impl const PartialEq for () {
18351849
#[inline]
18361850
fn eq(&self, _other: &()) -> bool {
18371851
true
@@ -1849,7 +1863,8 @@ mod impls {
18491863
macro_rules! eq_impl {
18501864
($($t:ty)*) => ($(
18511865
#[stable(feature = "rust1", since = "1.0.0")]
1852-
impl Eq for $t {}
1866+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1867+
impl const Eq for $t {}
18531868
)*)
18541869
}
18551870

@@ -1897,7 +1912,8 @@ mod impls {
18971912
macro_rules! partial_ord_impl {
18981913
($($t:ty)*) => ($(
18991914
#[stable(feature = "rust1", since = "1.0.0")]
1900-
impl PartialOrd for $t {
1915+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1916+
impl const PartialOrd for $t {
19011917
#[inline]
19021918
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
19031919
match (*self <= *other, *self >= *other) {
@@ -1914,15 +1930,17 @@ mod impls {
19141930
}
19151931

19161932
#[stable(feature = "rust1", since = "1.0.0")]
1917-
impl PartialOrd for () {
1933+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1934+
impl const PartialOrd for () {
19181935
#[inline]
19191936
fn partial_cmp(&self, _: &()) -> Option<Ordering> {
19201937
Some(Equal)
19211938
}
19221939
}
19231940

19241941
#[stable(feature = "rust1", since = "1.0.0")]
1925-
impl PartialOrd for bool {
1942+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1943+
impl const PartialOrd for bool {
19261944
#[inline]
19271945
fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
19281946
Some(self.cmp(other))
@@ -1936,7 +1954,8 @@ mod impls {
19361954
macro_rules! ord_impl {
19371955
($($t:ty)*) => ($(
19381956
#[stable(feature = "rust1", since = "1.0.0")]
1939-
impl PartialOrd for $t {
1957+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1958+
impl const PartialOrd for $t {
19401959
#[inline]
19411960
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
19421961
Some(crate::intrinsics::three_way_compare(*self, *other))
@@ -1946,7 +1965,8 @@ mod impls {
19461965
}
19471966

19481967
#[stable(feature = "rust1", since = "1.0.0")]
1949-
impl Ord for $t {
1968+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1969+
impl const Ord for $t {
19501970
#[inline]
19511971
fn cmp(&self, other: &Self) -> Ordering {
19521972
crate::intrinsics::three_way_compare(*self, *other)
@@ -1956,15 +1976,17 @@ mod impls {
19561976
}
19571977

19581978
#[stable(feature = "rust1", since = "1.0.0")]
1959-
impl Ord for () {
1979+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1980+
impl const Ord for () {
19601981
#[inline]
19611982
fn cmp(&self, _other: &()) -> Ordering {
19621983
Equal
19631984
}
19641985
}
19651986

19661987
#[stable(feature = "rust1", since = "1.0.0")]
1967-
impl Ord for bool {
1988+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
1989+
impl const Ord for bool {
19681990
#[inline]
19691991
fn cmp(&self, other: &bool) -> Ordering {
19701992
// Casting to i8's and converting the difference to an Ordering generates
@@ -2043,9 +2065,10 @@ mod impls {
20432065
}
20442066
}
20452067
#[stable(feature = "rust1", since = "1.0.0")]
2046-
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&B> for &A
2068+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2069+
impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&B> for &A
20472070
where
2048-
A: PartialOrd<B>,
2071+
A: [const] PartialOrd<B>,
20492072
{
20502073
#[inline]
20512074
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
@@ -2085,17 +2108,19 @@ mod impls {
20852108
}
20862109
}
20872110
#[stable(feature = "rust1", since = "1.0.0")]
2088-
impl<A: PointeeSized> Ord for &A
2111+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2112+
impl<A: PointeeSized> const Ord for &A
20892113
where
2090-
A: Ord,
2114+
A: [const] Ord,
20912115
{
20922116
#[inline]
20932117
fn cmp(&self, other: &Self) -> Ordering {
20942118
Ord::cmp(*self, *other)
20952119
}
20962120
}
20972121
#[stable(feature = "rust1", since = "1.0.0")]
2098-
impl<A: PointeeSized> Eq for &A where A: Eq {}
2122+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2123+
impl<A: PointeeSized> const Eq for &A where A: [const] Eq {}
20992124

21002125
// &mut pointers
21012126

@@ -2115,9 +2140,10 @@ mod impls {
21152140
}
21162141
}
21172142
#[stable(feature = "rust1", since = "1.0.0")]
2118-
impl<A: PointeeSized, B: PointeeSized> PartialOrd<&mut B> for &mut A
2143+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2144+
impl<A: PointeeSized, B: PointeeSized> const PartialOrd<&mut B> for &mut A
21192145
where
2120-
A: PartialOrd<B>,
2146+
A: [const] PartialOrd<B>,
21212147
{
21222148
#[inline]
21232149
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
@@ -2157,17 +2183,19 @@ mod impls {
21572183
}
21582184
}
21592185
#[stable(feature = "rust1", since = "1.0.0")]
2160-
impl<A: PointeeSized> Ord for &mut A
2186+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2187+
impl<A: PointeeSized> const Ord for &mut A
21612188
where
2162-
A: Ord,
2189+
A: [const] Ord,
21632190
{
21642191
#[inline]
21652192
fn cmp(&self, other: &Self) -> Ordering {
21662193
Ord::cmp(*self, *other)
21672194
}
21682195
}
21692196
#[stable(feature = "rust1", since = "1.0.0")]
2170-
impl<A: PointeeSized> Eq for &mut A where A: Eq {}
2197+
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2198+
impl<A: PointeeSized> const Eq for &mut A where A: [const] Eq {}
21712199

21722200
#[stable(feature = "rust1", since = "1.0.0")]
21732201
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]

0 commit comments

Comments
 (0)