DSTify PartialEq, PartialOrd, Eq, Ord

This commit is contained in:
Jorge Aparicio 2014-10-29 20:11:16 -05:00
parent 1a94375426
commit 2896278313
3 changed files with 329 additions and 0 deletions

View File

@ -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 {
@ -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).
///
@ -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
@ -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]
@ -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.
@ -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 {}
@ -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 {
@ -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`
@ -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(
@ -393,6 +531,8 @@ 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]
@ -400,6 +540,8 @@ mod impls {
#[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]
@ -415,15 +557,55 @@ 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]
@ -431,6 +613,8 @@ mod impls {
#[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]
@ -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 {}
}

View File

@ -1555,6 +1555,8 @@ pub mod bytes {
// Boilerplate traits
//
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:PartialEq> PartialEq for &'a [T] {
fn eq(&self, other: & &'a [T]) -> bool {
@ -1567,15 +1569,36 @@ impl<'a,T:PartialEq> PartialEq for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: PartialEq> PartialEq for [T] {
fn eq(&self, other: &[T]) -> bool {
self.len() == other.len() &&
order::eq(self.iter(), other.iter())
}
fn ne(&self, other: &[T]) -> bool {
self.len() != other.len() ||
order::ne(self.iter(), other.iter())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Eq> Eq for &'a [T] {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: Eq> Eq for [T] {}
#[unstable = "waiting for DST"]
impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for [T] {
#[inline]
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:PartialEq> PartialEq for &'a mut [T] {
fn eq(&self, other: & &'a mut [T]) -> bool {
@ -1588,6 +1611,8 @@ impl<'a,T:PartialEq> PartialEq for &'a mut [T] {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Eq> Eq for &'a mut [T] {}
@ -1597,6 +1622,8 @@ impl<'a,T:PartialEq, V: AsSlice<T>> Equiv<V> for &'a mut [T] {
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Ord> Ord for &'a [T] {
fn cmp(&self, other: & &'a [T]) -> Ordering {
@ -1604,6 +1631,16 @@ impl<'a,T:Ord> Ord for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: Ord> Ord for [T] {
fn cmp(&self, other: &[T]) -> Ordering {
order::cmp(self.iter(), other.iter())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
#[inline]
@ -1628,6 +1665,31 @@ impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: PartialOrd> PartialOrd for [T] {
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
order::partial_cmp(self.iter(), other.iter())
}
#[inline]
fn lt(&self, other: &[T]) -> bool {
order::lt(self.iter(), other.iter())
}
#[inline]
fn le(&self, other: &[T]) -> bool {
order::le(self.iter(), other.iter())
}
#[inline]
fn ge(&self, other: &[T]) -> bool {
order::ge(self.iter(), other.iter())
}
#[inline]
fn gt(&self, other: &[T]) -> bool {
order::gt(self.iter(), other.iter())
}
}
/// Extension methods for immutable slices containing integers.
#[experimental]
pub trait ImmutableIntSlice<U, S> for Sized? {

View File

@ -1122,6 +1122,8 @@ pub mod traits {
use ops;
use str::{Str, StrSlice, eq_slice};
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> Ord for &'a str {
#[inline]
fn cmp(&self, other: & &'a str) -> Ordering {
@ -1137,6 +1139,24 @@ pub mod traits {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl Ord for str {
#[inline]
fn cmp(&self, other: &str) -> Ordering {
for (s_b, o_b) in self.bytes().zip(other.bytes()) {
match s_b.cmp(&o_b) {
Greater => return Greater,
Less => return Less,
Equal => ()
}
}
self.len().cmp(&other.len())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> PartialEq for &'a str {
#[inline]
fn eq(&self, other: & &'a str) -> bool {
@ -1146,8 +1166,25 @@ pub mod traits {
fn ne(&self, other: & &'a str) -> bool { !(*self).eq(other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl PartialEq for str {
#[inline]
fn eq(&self, other: &str) -> bool {
eq_slice(self, other)
}
#[inline]
fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> Eq for &'a str {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl Eq for str {}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> PartialOrd for &'a str {
#[inline]
fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
@ -1155,6 +1192,14 @@ pub mod traits {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl PartialOrd for str {
#[inline]
fn partial_cmp(&self, other: &str) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<S: Str> Equiv<S> for str {
#[inline]
fn equiv(&self, other: &S) -> bool { eq_slice(self, other.as_slice()) }