Skip to content

DSTify PartialEq, PartialOrd, Eq, Ord #18467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 6, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
DSTify PartialEq, PartialOrd, Eq, Ord
  • Loading branch information
Jorge Aparicio committed Nov 6, 2014
commit 2896278313ede1b24b47c88bafe684adabbc92d4
222 changes: 222 additions & 0 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ use option::{Option, Some, None};
///
/// Eventually, this will be implemented by default for types that implement
/// `Eq`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[lang="eq"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialEq {
Expand All @@ -66,6 +68,31 @@ pub trait PartialEq {
fn ne(&self, other: &Self) -> bool { !self.eq(other) }
}

/// Trait for values that can be compared for equality and inequality.
///
/// This trait allows for partial equality, for types that do not have an
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not `Eq`.
///
/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
/// in terms of it by default. Any manual implementation of `ne` *must* respect
/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
/// only if `a != b`.
///
/// Eventually, this will be implemented by default for types that implement
/// `Eq`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[lang="eq"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialEq for Sized? {
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
fn eq(&self, other: &Self) -> bool;

/// This method tests for `!=`.
#[inline]
fn ne(&self, other: &Self) -> bool { !self.eq(other) }
}

/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
Expand All @@ -75,6 +102,8 @@ pub trait PartialEq {
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[unstable = "Definition may change slightly after trait reform"]
pub trait Eq: PartialEq {
// FIXME #13101: this method is used solely by #[deriving] to
Expand All @@ -89,6 +118,30 @@ pub trait Eq: PartialEq {
fn assert_receiver_is_total_eq(&self) {}
}

/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
/// This means, that in addition to `a == b` and `a != b` being strict
/// inverses, the equality must be (for all `a`, `b` and `c`):
///
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Definition may change slightly after trait reform"]
pub trait Eq for Sized?: PartialEq {
// FIXME #13101: this method is used solely by #[deriving] to
// assert that every component of a type implements #[deriving]
// itself, the current deriving infrastructure means doing this
// assertion without using a method on this trait is nearly
// impossible.
//
// This should never be implemented by hand.
#[doc(hidden)]
#[inline(always)]
fn assert_receiver_is_total_eq(&self) {}
}

/// An ordering is, e.g, a result of a comparison between two values.
#[deriving(Clone, PartialEq, Show)]
#[stable]
Expand Down Expand Up @@ -145,6 +198,8 @@ impl Ordering {
/// true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[unstable = "Definition may change slightly after trait reform"]
pub trait Ord: Eq + PartialOrd {
/// This method returns an ordering between `self` and `other` values.
Expand All @@ -160,6 +215,31 @@ pub trait Ord: Eq + PartialOrd {
fn cmp(&self, other: &Self) -> Ordering;
}

/// Trait for types that form a [total order](
/// https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
///
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is
/// true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Definition may change slightly after trait reform"]
pub trait Ord for Sized?: Eq + PartialOrd {
/// This method returns an ordering between `self` and `other` values.
///
/// By convention, `self.cmp(&other)` returns the ordering matching
/// the expression `self <operator> other` if true. For example:
///
/// ```
/// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10
/// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5
/// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5
/// ```
fn cmp(&self, other: &Self) -> Ordering;
}

#[unstable = "Trait is unstable."]
impl Eq for Ordering {}

Expand Down Expand Up @@ -188,6 +268,8 @@ impl PartialOrd for Ordering {
/// which do not have a total order. For example, for floating point numbers,
/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
/// 5.11).
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[lang="ord"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialOrd: PartialEq {
Expand Down Expand Up @@ -232,6 +314,60 @@ pub trait PartialOrd: PartialEq {
}
}

/// Trait for values that can be compared for a sort-order.
///
/// PartialOrd only requires implementation of the `partial_cmp` method,
/// with the others generated from default implementations.
///
/// However it remains possible to implement the others separately for types
/// which do not have a total order. For example, for floating point numbers,
/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
/// 5.11).
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[lang="ord"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialOrd for Sized?: PartialEq {
/// This method returns an ordering between `self` and `other` values
/// if one exists.
fn partial_cmp(&self, other: &Self) -> Option<Ordering>;

/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
#[inline]
fn lt(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Less) => true,
_ => false,
}
}

/// This method tests less than or equal to (`<=`).
#[inline]
fn le(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Less) | Some(Equal) => true,
_ => false,
}
}

/// This method tests greater than (`>`).
#[inline]
fn gt(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Greater) => true,
_ => false,
}
}

/// This method tests greater than or equal to (`>=`).
#[inline]
fn ge(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Greater) | Some(Equal) => true,
_ => false,
}
}
}

/// The equivalence relation. Two values may be equivalent even if they are
/// of different types. The most common use case for this relation is
/// container types; e.g. it is often desirable to be able to use `&str`
Expand Down Expand Up @@ -286,6 +422,8 @@ pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
mod impls {
use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering,
Less, Greater, Equal};
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
use kinds::Sized;
use option::{Option, Some, None};

macro_rules! partial_eq_impl(
Expand Down Expand Up @@ -393,13 +531,17 @@ mod impls {
ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)

// & pointers
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialEq> PartialEq for &'a T {
#[inline]
fn eq(&self, other: & &'a T) -> bool { *(*self) == *(*other) }
#[inline]
fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialOrd> PartialOrd for &'a T {
#[inline]
Expand All @@ -415,22 +557,64 @@ mod impls {
#[inline]
fn gt(&self, other: & &'a T) -> bool { *(*self) > *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Ord> Ord for &'a T {
#[inline]
fn cmp(&self, other: & &'a T) -> Ordering { (**self).cmp(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Eq> Eq for &'a T {}

#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialEq> PartialEq for &'a T {
#[inline]
fn eq(&self, other: & &'a T) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: & &'a T) -> bool { PartialEq::ne(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialOrd> PartialOrd for &'a T {
#[inline]
fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: & &'a T) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
fn le(&self, other: & &'a T) -> bool { PartialOrd::le(*self, *other) }
#[inline]
fn ge(&self, other: & &'a T) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
fn gt(&self, other: & &'a T) -> bool { PartialOrd::gt(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Ord> Ord for &'a T {
#[inline]
fn cmp(&self, other: & &'a T) -> Ordering { Ord::cmp(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Eq> Eq for &'a T {}

// &mut pointers
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialEq> PartialEq for &'a mut T {
#[inline]
fn eq(&self, other: &&'a mut T) -> bool { **self == *(*other) }
#[inline]
fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialOrd> PartialOrd for &'a mut T {
#[inline]
Expand All @@ -446,11 +630,49 @@ mod impls {
#[inline]
fn gt(&self, other: &&'a mut T) -> bool { **self > **other }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Ord> Ord for &'a mut T {
#[inline]
fn cmp(&self, other: &&'a mut T) -> Ordering { (**self).cmp(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Eq> Eq for &'a mut T {}

#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialEq> PartialEq for &'a mut T {
#[inline]
fn eq(&self, other: &&'a mut T) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: &&'a mut T) -> bool { PartialEq::ne(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialOrd> PartialOrd for &'a mut T {
#[inline]
fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&'a mut T) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
fn le(&self, other: &&'a mut T) -> bool { PartialOrd::le(*self, *other) }
#[inline]
fn ge(&self, other: &&'a mut T) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
fn gt(&self, other: &&'a mut T) -> bool { PartialOrd::gt(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Ord> Ord for &'a mut T {
#[inline]
fn cmp(&self, other: &&'a mut T) -> Ordering { Ord::cmp(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Eq> Eq for &'a mut T {}
}
Loading