about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJorge Aparicio <japaricious@gmail.com>2014-10-29 20:11:16 -0500
committerJorge Aparicio <japaricious@gmail.com>2014-11-05 20:12:00 -0500
commit2896278313ede1b24b47c88bafe684adabbc92d4 (patch)
tree2150e45567ef3738d42d639862dfb56ad8c91e4f
parent1a943754262a621fb06db4de7ca657a225706531 (diff)
downloadrust-2896278313ede1b24b47c88bafe684adabbc92d4.tar.gz
rust-2896278313ede1b24b47c88bafe684adabbc92d4.zip
DSTify PartialEq, PartialOrd, Eq, Ord
-rw-r--r--src/libcore/cmp.rs222
-rw-r--r--src/libcore/slice.rs62
-rw-r--r--src/libcore/str.rs45
3 files changed, 329 insertions, 0 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index d7c2b52b8de..6e87fe4ced0 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -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 {}
 }
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 317a6e224bc..3cc904162a1 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -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? {
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 10c0f68dd5d..175f9f3f577 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -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()) }