Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions library/core/src/bstr/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,35 @@ 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)
}
}

#[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<Ordering> {
PartialOrd::partial_cmp(&self.0, &other.0)
}
}

#[unstable(feature = "bstr", issue = "134915")]
impl PartialEq<ByteStr> for ByteStr {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const PartialEq<ByteStr> for ByteStr {
#[inline]
fn eq(&self, other: &ByteStr) -> bool {
&self.0 == &other.0
}
}

#[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 {
Expand Down
9 changes: 6 additions & 3 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -667,15 +668,17 @@ 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<Ordering> {
self.to_bytes().partial_cmp(&other.to_bytes())
}
}

#[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())
Expand Down
26 changes: 18 additions & 8 deletions library/core/src/panic/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -56,20 +57,29 @@ impl PartialEq for Location<'_> {
}

#[stable(feature = "panic_hooks", since = "1.10.0")]
impl Eq for Location<'_> {}
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const Eq for Location<'_> {}

#[stable(feature = "panic_hooks", since = "1.10.0")]
impl Ord for Location<'_> {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const Ord for Location<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.file()
.cmp(other.file())
.then_with(|| self.line.cmp(&other.line))
.then_with(|| self.col.cmp(&other.col))
// FIXME(const-hack): This uses match instead of `then_with` as a
// workaround for the lack of const closures. Revert to using
// `then_with` once const closures are available.
match self.file().cmp(other.file()) {
Ordering::Equal => match self.line.cmp(&other.line) {
Ordering::Equal => self.col.cmp(&other.col),
ordering => ordering,
},
ordering => ordering,
}
}
}

#[stable(feature = "panic_hooks", since = "1.10.0")]
impl PartialOrd for Location<'_> {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl const PartialOrd for Location<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
Expand Down
109 changes: 74 additions & 35 deletions library/core/src/slice/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -28,7 +30,8 @@ impl<T: [const] Eq> const Eq for [T] {}

/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Ord for [T] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] Ord> const Ord for [T] {
fn cmp(&self, other: &[T]) -> Ordering {
SliceOrd::compare(self, other)
}
Expand All @@ -47,7 +50,8 @@ const fn as_underlying(x: ControlFlow<bool>) -> u8 {

/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for [T] {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<T: [const] PartialOrd> const PartialOrd for [T] {
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
SlicePartialOrd::partial_compare(self, other)
Expand Down Expand Up @@ -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<Ordering>;
}

#[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<bool>;
fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
}

type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
type AlwaysBreak<B> = ControlFlow<B, Infallible>;

impl<A: PartialOrd> SlicePartialOrd for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] PartialOrd> const SlicePartialOrd for A {
default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
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<B>(a: &B, b: &B) -> ControlFlow<Option<Ordering>>
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<Option<Ordering>, Infallible> {
ControlFlow::Break(usize::partial_cmp(a, b))
}

let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b
}
}

impl<A: PartialOrd> SliceChain for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] PartialOrd> const SliceChain for A {
default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
}
Expand All @@ -203,21 +218,31 @@ impl<A: PartialOrd> 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<B>,
len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
) -> ControlFlow<B, C> {
elem_chain: E,
len_chain: L,
) -> ControlFlow<B, C>
where
E: [const] Destruct + [const] Fn(&'l A, &'r A) -> ControlFlow<B>,
L: [const] Destruct + for<'a> [const] FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
{
let l = cmp::min(left.len(), right.len());

// Slice to the loop iteration range to enable bound check
// elimination in the compiler
let lhs = &left[..l];
let rhs = &right[..l];

for i in 0..l {
// FIXME(const-hack): This uses a `while` loop instead of `for` as a
// workaround for the lack of const iterators. Revert to using `for` once
// const iterators are available.
let mut i = 0;
while i < l {
elem_chain(&lhs[i], &rhs[i])?;
i += 1;
}

len_chain(&left.len(), &right.len())
Expand All @@ -244,41 +269,56 @@ impl<A: [const] AlwaysApplicableOrd> 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 {}
)*
}
}

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>,
[T: [const] AlwaysApplicableOrd] &T,
[T: [const] AlwaysApplicableOrd] &mut T,
[T: [const] AlwaysApplicableOrd] Option<T>,
}

impl<T: ?Sized> AlwaysApplicableOrd for *const T {}
impl<T: ?Sized> 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<A: Ord> SliceOrd for A {
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
impl<A: [const] Ord> 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<B>(a: &B, b: &B) -> ControlFlow<Ordering>
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<Ordering, Infallible> {
ControlFlow::Break(usize::cmp(a, b))
}

let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
b
}
Expand Down Expand Up @@ -334,7 +374,6 @@ impl<A: [const] Ord + [const] UnsignedBytewiseOrd> 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<A: [const] PartialOrd + [const] UnsignedBytewiseOrd> const SliceChain for A {
#[inline]
Expand Down
6 changes: 4 additions & 2 deletions library/core/src/str/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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<Ordering> {
Some(self.cmp(other))
Expand Down
Loading