]> git.lizzy.rs Git - rust.git/commitdiff
Implement RFC#28: Add PartialOrd::partial_cmp
authorSteven Fackler <sfackler@gmail.com>
Wed, 18 Jun 2014 06:25:51 +0000 (23:25 -0700)
committerSteven Fackler <sfackler@gmail.com>
Mon, 30 Jun 2014 04:42:09 +0000 (21:42 -0700)
I ended up altering the semantics of Json's PartialOrd implementation.
It used to be the case that Null < Null, but I can't think of any reason
for an ordering other than the default one so I just switched it over to
using the derived implementation.

This also fixes broken `PartialOrd` implementations for `Vec` and
`TreeMap`.

RFC: 0028-partial-cmp

28 files changed:
src/liballoc/owned.rs
src/liballoc/rc.rs
src/libcollections/btree.rs
src/libcollections/dlist.rs
src/libcollections/str.rs
src/libcollections/treemap.rs
src/libcollections/vec.rs
src/libcore/cmp.rs
src/libcore/iter.rs
src/libcore/ptr.rs
src/libcore/slice.rs
src/libcore/str.rs
src/libcore/tuple.rs
src/libcoretest/iter.rs
src/libgraphviz/maybe_owned_vec.rs
src/libnum/bigint.rs
src/libnum/rational.rs
src/libsemver/lib.rs
src/libserialize/json.rs
src/libstd/gc.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/test/compile-fail/deriving-span-PartialOrd-enum-struct-variant.rs
src/test/compile-fail/deriving-span-PartialOrd-enum.rs
src/test/compile-fail/deriving-span-PartialOrd-struct.rs
src/test/compile-fail/deriving-span-PartialOrd-tuple-struct.rs
src/test/compile-fail/issue-3344.rs
src/test/run-pass/cmp-default.rs
src/test/run-pass/deriving-cmp-shortcircuit.rs

index 33afa806f4e391c180ebd6eedcfe11c6590695c7..addec396bbef8715d14e88ea237671424b1621b2 100644 (file)
@@ -18,6 +18,7 @@
 use core::intrinsics;
 use core::kinds::Send;
 use core::mem;
+use core::option::Option;
 use core::raw::TraitObject;
 use core::result::{Ok, Err, Result};
 
@@ -64,6 +65,10 @@ fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
     fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
 }
 impl<T:PartialOrd> PartialOrd for Box<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
+        (**self).partial_cmp(*other)
+    }
     #[inline]
     fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
     #[inline]
index a3ca72f1547eda84a9146b906e1882436e9aa854..0746f0a0f0451f5c747c2eb8450bb66f3290de3c 100644 (file)
@@ -162,6 +162,11 @@ fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
 impl<T: Eq> Eq for Rc<T> {}
 
 impl<T: PartialOrd> PartialOrd for Rc<T> {
+    #[inline(always)]
+    fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
+        (**self).partial_cmp(&**other)
+    }
+
     #[inline(always)]
     fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
 
index 64bee05a379a72321a34898880da39dc45bac83d..92abfaad3483301016fa4449e51221967446f2c9 100644 (file)
@@ -107,8 +107,8 @@ fn eq(&self, other: &BTree<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for BTree<K, V> {}
 
 impl<K: Ord, V: Eq> PartialOrd for BTree<K, V> {
-    fn lt(&self, other: &BTree<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &BTree<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -229,8 +229,8 @@ fn eq(&self, other: &Node<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for Node<K, V> {}
 
 impl<K: Ord, V: Eq> PartialOrd for Node<K, V> {
-    fn lt(&self, other: &Node<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &Node<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -408,8 +408,8 @@ fn eq(&self, other: &Leaf<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for Leaf<K, V> {}
 
 impl<K: Ord, V: Eq> PartialOrd for Leaf<K, V> {
-    fn lt(&self, other: &Leaf<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &Leaf<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -638,8 +638,8 @@ fn eq(&self, other: &Branch<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for Branch<K, V> {}
 
 impl<K: Ord, V: Eq> PartialOrd for Branch<K, V> {
-    fn lt(&self, other: &Branch<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &Branch<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -706,8 +706,8 @@ fn eq(&self, other: &LeafElt<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for LeafElt<K, V> {}
 
 impl<K: Ord, V: Eq> PartialOrd for LeafElt<K, V> {
-    fn lt(&self, other: &LeafElt<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &LeafElt<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -755,8 +755,8 @@ fn eq(&self, other: &BranchElt<K, V>) -> bool {
 impl<K: Ord, V: Eq> Eq for BranchElt<K, V>{}
 
 impl<K: Ord, V: Eq> PartialOrd for BranchElt<K, V> {
-    fn lt(&self, other: &BranchElt<K, V>) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &BranchElt<K, V>) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
index 7ea5c482e61f206b6b466b33dd4654362aac5ec8..4114c8cb1c4ddc8b7a5a489de9ea5ee1f7a8c518 100644 (file)
@@ -595,17 +595,8 @@ fn ne(&self, other: &DList<A>) -> bool {
 }
 
 impl<A: PartialOrd> PartialOrd for DList<A> {
-    fn lt(&self, other: &DList<A>) -> bool {
-        iter::order::lt(self.iter(), other.iter())
-    }
-    fn le(&self, other: &DList<A>) -> bool {
-        iter::order::le(self.iter(), other.iter())
-    }
-    fn gt(&self, other: &DList<A>) -> bool {
-        iter::order::gt(self.iter(), other.iter())
-    }
-    fn ge(&self, other: &DList<A>) -> bool {
-        iter::order::ge(self.iter(), other.iter())
+    fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
+        iter::order::partial_cmp(self.iter(), other.iter())
     }
 }
 
index 2d84c733b09e91136f193c84131de7ca94113798..b5424d1683fca566bba7a5296876c36c10113cea 100644 (file)
@@ -572,8 +572,8 @@ impl<'a> Eq for MaybeOwned<'a> {}
 
 impl<'a> PartialOrd for MaybeOwned<'a> {
     #[inline]
-    fn lt(&self, other: &MaybeOwned) -> bool {
-        self.as_slice().lt(&other.as_slice())
+    fn partial_cmp(&self, other: &MaybeOwned) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
index 568baa6fc405236465060b8273edf52cd2deeb05..becceffe6d0270254fe0017f0c3be5e4cee6abb9 100644 (file)
@@ -56,23 +56,11 @@ fn eq(&self, other: &TreeMap<K, V>) -> bool {
     }
 }
 
-// Lexicographical comparison
-fn lt<K: PartialOrd + Ord, V: PartialOrd>(a: &TreeMap<K, V>,
-                                 b: &TreeMap<K, V>) -> bool {
-    // the Zip iterator is as long as the shortest of a and b.
-    for ((key_a, value_a), (key_b, value_b)) in a.iter().zip(b.iter()) {
-        if *key_a < *key_b { return true; }
-        if *key_a > *key_b { return false; }
-        if *value_a < *value_b { return true; }
-        if *value_a > *value_b { return false; }
-    }
-
-    a.len() < b.len()
-}
-
-impl<K: PartialOrd + Ord, V: PartialOrd> PartialOrd for TreeMap<K, V> {
+impl<K: Ord, V: PartialOrd> PartialOrd for TreeMap<K, V> {
     #[inline]
-    fn lt(&self, other: &TreeMap<K, V>) -> bool { lt(self, other) }
+    fn partial_cmp(&self, other: &TreeMap<K, V>) -> Option<Ordering> {
+        iter::order::partial_cmp(self.iter(), other.iter())
+    }
 }
 
 impl<K: Ord + Show, V: Show> Show for TreeMap<K, V> {
@@ -568,9 +556,11 @@ impl<T: PartialEq + Ord> PartialEq for TreeSet<T> {
     fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
 }
 
-impl<T: PartialOrd + Ord> PartialOrd for TreeSet<T> {
+impl<T: Ord> PartialOrd for TreeSet<T> {
     #[inline]
-    fn lt(&self, other: &TreeSet<T>) -> bool { self.map < other.map }
+    fn partial_cmp(&self, other: &TreeSet<T>) -> Option<Ordering> {
+        self.map.partial_cmp(&other.map)
+    }
 }
 
 impl<T: Ord + Show> Show for TreeSet<T> {
index 8e6e86ce36ecd6a3e34d48e23868ab087ae9bef3..2ffc168f82c0eef4b4d77244a873ed3cd327d1a6 100644 (file)
@@ -389,8 +389,8 @@ fn eq(&self, other: &Vec<T>) -> bool {
 
 impl<T: PartialOrd> PartialOrd for Vec<T> {
     #[inline]
-    fn lt(&self, other: &Vec<T>) -> bool {
-        self.as_slice() < other.as_slice()
+    fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
+        self.as_slice().partial_cmp(&other.as_slice())
     }
 }
 
index a29aba6df980e48126f530f827997af5a86bc3b6..8696d385c44884d6d257b03818de2360e7f574c3 100644 (file)
 //! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
 //! ```
 
+use option::{Option, Some};
+#[cfg(stage0)]
+use option::None;
+
 /// Trait for values that can be compared for equality and inequality.
 ///
 /// This trait allows for partial equality, for types that do not have an
@@ -127,7 +131,9 @@ fn cmp(&self, other: &Ordering) -> Ordering {
 
 impl PartialOrd for Ordering {
     #[inline]
-    fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
+    fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
+        (*self as int).partial_cmp(&(*other as int))
+    }
 }
 
 /// Combine orderings, lexically.
@@ -145,7 +151,7 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
 
 /// Trait for values that can be compared for a sort-order.
 ///
-/// PartialOrd only requires implementation of the `lt` method,
+/// 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
@@ -154,20 +160,57 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
 /// 5.11).
 #[lang="ord"]
 pub trait PartialOrd: PartialEq {
+    /// This method returns an ordering between `self` and `other` values
+    /// if one exists.
+    #[cfg(stage0)]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        match (!self.lt(other), !other.lt(self)) {
+            (false, false) => None,
+            (false, true) => Some(Less),
+            (true, false) => Some(Greater),
+            (true, true) => Some(Equal),
+        }
+    }
+
+    /// This method returns an ordering between `self` and `other` values
+    /// if one exists.
+    #[cfg(not(stage0))]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering>;
+
     /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
-    fn lt(&self, other: &Self) -> bool;
+    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 { !other.lt(self) }
+    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 {  other.lt(self) }
+    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 { !self.lt(other) }
+    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
@@ -195,6 +238,7 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
 mod impls {
     use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering,
               Less, Greater, Equal};
+    use option::{Option, Some, None};
 
     macro_rules! eq_impl(
         ($($t:ty)*) => ($(
@@ -227,6 +271,15 @@ impl Eq for $t {}
     macro_rules! ord_impl(
         ($($t:ty)*) => ($(
             impl PartialOrd for $t {
+                #[inline]
+                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                    match (self <= other, self >= other) {
+                        (false, false) => None,
+                        (false, true) => Some(Greater),
+                        (true, false) => Some(Less),
+                        (true, true) => Some(Equal),
+                    }
+                }
                 #[inline]
                 fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
                 #[inline]
@@ -241,13 +294,15 @@ fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
 
     impl PartialOrd for () {
         #[inline]
-        fn lt(&self, _other: &()) -> bool { false }
+        fn partial_cmp(&self, _: &()) -> Option<Ordering> {
+            Some(Equal)
+        }
     }
 
     impl PartialOrd for bool {
         #[inline]
-        fn lt(&self, other: &bool) -> bool {
-            (*self as u8) < (*other as u8)
+        fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
+            (*self as u8).partial_cmp(&(*other as u8))
         }
     }
 
@@ -288,6 +343,10 @@ fn eq(&self, other: & &'a T) -> bool { *(*self) == *(*other) }
         fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) }
     }
     impl<'a, T: PartialOrd> PartialOrd for &'a T {
+        #[inline]
+        fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
+            (**self).partial_cmp(*other)
+        }
         #[inline]
         fn lt(&self, other: & &'a T) -> bool { *(*self) < *(*other) }
         #[inline]
@@ -311,6 +370,10 @@ fn eq(&self, other: &&'a mut T) -> bool { **self == *(*other) }
         fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) }
     }
     impl<'a, T: PartialOrd> PartialOrd for &'a mut T {
+        #[inline]
+        fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
+            (**self).partial_cmp(*other)
+        }
         #[inline]
         fn lt(&self, other: &&'a mut T) -> bool { **self < **other }
         #[inline]
index 1445376d7db21615f2840dbf5865aebdc3847248..5895d871dbe18e2bb3467f72c09f1fb630e3b9c0 100644 (file)
@@ -2183,7 +2183,7 @@ fn idx(&mut self, _: uint) -> Option<A> { Some(self.element.clone()) }
 pub mod order {
     use cmp;
     use cmp::{Eq, Ord, PartialOrd, PartialEq};
-    use option::{Some, None};
+    use option::{Option, Some, None};
     use super::Iterator;
 
     /// Compare `a` and `b` for equality using `Eq`
@@ -2212,6 +2212,22 @@ pub fn cmp<A: Ord, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> cmp::O
         }
     }
 
+    /// Order `a` and `b` lexicographically using `PartialOrd`
+    pub fn partial_cmp<A: PartialOrd, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S)
+            -> Option<cmp::Ordering> {
+        loop {
+            match (a.next(), b.next()) {
+                (None, None) => return Some(cmp::Equal),
+                (None, _   ) => return Some(cmp::Less),
+                (_   , None) => return Some(cmp::Greater),
+                (Some(x), Some(y)) => match x.partial_cmp(&y) {
+                    Some(cmp::Equal) => (),
+                    non_eq => return non_eq,
+                },
+            }
+        }
+    }
+
     /// Compare `a` and `b` for equality (Using partial equality, `PartialEq`)
     pub fn eq<A: PartialEq, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
         loop {
index cecc6bab683f5db2fe8287e1a453305480d1feff..093591cd796d1cf4026605f338da2be55a87af46 100644 (file)
@@ -93,7 +93,7 @@
 use iter::{range, Iterator};
 use option::{Some, None, Option};
 
-use cmp::{PartialEq, Eq, PartialOrd, Equiv};
+use cmp::{PartialEq, Eq, PartialOrd, Equiv, Ordering, Less, Equal, Greater};
 
 /// Create a null pointer.
 ///
@@ -488,11 +488,51 @@ fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
 
 // Comparison for pointers
 impl<T> PartialOrd for *const T {
+    #[inline]
+    fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
+        if self < other {
+            Some(Less)
+        } else if self == other {
+            Some(Equal)
+        } else {
+            Some(Greater)
+        }
+    }
+
     #[inline]
     fn lt(&self, other: &*const T) -> bool { *self < *other }
+
+    #[inline]
+    fn le(&self, other: &*const T) -> bool { *self <= *other }
+
+    #[inline]
+    fn gt(&self, other: &*const T) -> bool { *self > *other }
+
+    #[inline]
+    fn ge(&self, other: &*const T) -> bool { *self >= *other }
 }
 
 impl<T> PartialOrd for *mut T {
+    #[inline]
+    fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
+        if self < other {
+            Some(Less)
+        } else if self == other {
+            Some(Equal)
+        } else {
+            Some(Greater)
+        }
+    }
+
     #[inline]
     fn lt(&self, other: &*mut T) -> bool { *self < *other }
+
+    #[inline]
+    fn le(&self, other: &*mut T) -> bool { *self <= *other }
+
+    #[inline]
+    fn gt(&self, other: &*mut T) -> bool { *self > *other }
+
+    #[inline]
+    fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 }
index 6340633410374f9e560ae934f2d2db6e7069be0a..a9e7efdf05a5ada6177858be6609b33f093ee568 100644 (file)
@@ -253,6 +253,7 @@ pub mod traits {
     use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv};
     use iter::order;
     use collections::Collection;
+    use option::Option;
 
     impl<'a,T:PartialEq> PartialEq for &'a [T] {
         fn eq(&self, other: & &'a [T]) -> bool {
@@ -279,6 +280,11 @@ fn cmp(&self, other: & &'a [T]) -> Ordering {
     }
 
     impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
+        #[inline]
+        fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> {
+            order::partial_cmp(self.iter(), other.iter())
+        }
+        #[inline]
         fn lt(&self, other: & &'a [T]) -> bool {
             order::lt(self.iter(), other.iter())
         }
index 21de4cdf59fb102e76e3c400728727de3e5eccf8..de23e04393be1bb99e22a3c66d2a0c79d94160e4 100644 (file)
@@ -931,7 +931,7 @@ pub mod traits {
     use cmp::{Ord, Ordering, Less, Equal, Greater, PartialEq, PartialOrd, Equiv, Eq};
     use collections::Collection;
     use iter::Iterator;
-    use option::{Some, None};
+    use option::{Option, Some, None};
     use str::{Str, StrSlice, eq_slice};
 
     impl<'a> Ord for &'a str {
@@ -962,7 +962,9 @@ impl<'a> Eq for &'a str {}
 
     impl<'a> PartialOrd for &'a str {
         #[inline]
-        fn lt(&self, other: & &'a str) -> bool { self.cmp(other) == Less }
+        fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
+            Some(self.cmp(other))
+        }
     }
 
     impl<'a, S: Str> Equiv<S> for &'a str {
index f44bce33547126df75ae6cb68418e1b02d5071c0..0e3722894bc467771f52af3266c888691733581a 100644 (file)
@@ -64,6 +64,7 @@
 use clone::Clone;
 use cmp::*;
 use default::Default;
+use option::{Option, Some};
 
 // macro for implementing n-ary tuple functions and operations
 macro_rules! tuple_impls {
@@ -125,6 +126,10 @@ fn ne(&self, other: &($($T,)+)) -> bool {
             impl<$($T:Eq),+> Eq for ($($T,)+) {}
 
             impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
+                #[inline]
+                fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
+                    lexical_partial_cmp!($(self.$refN(), other.$refN()),+)
+                }
                 #[inline]
                 fn lt(&self, other: &($($T,)+)) -> bool {
                     lexical_ord!(lt, $(self.$refN(), other.$refN()),+)
@@ -172,6 +177,16 @@ macro_rules! lexical_ord {
     ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) };
 }
 
+macro_rules! lexical_partial_cmp {
+    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        match ($a).partial_cmp($b) {
+            Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
+            ordering   => ordering
+        }
+    };
+    ($a:expr, $b:expr) => { ($a).partial_cmp($b) };
+}
+
 macro_rules! lexical_cmp {
     ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
         match ($a).cmp($b) {
index bc55b17b3467f5aac86feb6fdd4b38f36603c4ca..86b5ffece41033c7a8b851a637b2490c4b2ccee9 100644 (file)
@@ -707,8 +707,8 @@ fn eq(&self, _: &Foo) -> bool {
     }
 
     impl PartialOrd for Foo {
-        fn lt(&self, _: &Foo) -> bool {
-            false
+        fn partial_cmp(&self, _: &Foo) -> Option<Ordering> {
+            None
         }
     }
 
index 026db9d96f676e86ab54fcbf5fe81994d7c81f4e..bd19f19cec6b2f86a9a1beee94f87b60c3720eab 100644 (file)
@@ -73,8 +73,8 @@ fn eq(&self, other: &MaybeOwnedVector<T>) -> bool {
 impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {}
 
 impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> {
-    fn lt(&self, other: &MaybeOwnedVector<T>) -> bool {
-        self.as_slice().lt(&other.as_slice())
+    fn partial_cmp(&self, other: &MaybeOwnedVector<T>) -> Option<Ordering> {
+        self.as_slice().partial_cmp(&other.as_slice())
     }
 }
 
index 9011aafc009d381af47b0e15d43fde39a71cd449..cc3753def59f4cc2a6ed98d1080f4a36fc33ae28 100644 (file)
@@ -91,8 +91,8 @@ impl Eq for BigUint {}
 
 impl PartialOrd for BigUint {
     #[inline]
-    fn lt(&self, other: &BigUint) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &BigUint) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
@@ -816,8 +816,8 @@ impl Eq for BigInt {}
 
 impl PartialOrd for BigInt {
     #[inline]
-    fn lt(&self, other: &BigInt) -> bool {
-        self.cmp(other) == Less
+    fn partial_cmp(&self, other: &BigInt) -> Option<Ordering> {
+        Some(self.cmp(other))
     }
 }
 
index 971b6b1b51b2dbecac6b5bd7ca4ec49052bcadc5..9a455edf2c086e8d034b5c178847fda15b556ae5 100644 (file)
@@ -193,7 +193,8 @@ fn $method(&self, other: &Ratio<T>) -> $res {
     };
 }
 cmp_impl!(impl PartialEq, eq, ne)
-cmp_impl!(impl PartialOrd, lt, gt, le, ge)
+cmp_impl!(impl PartialOrd, lt -> bool, gt -> bool, le -> bool, ge -> bool,
+          partial_cmp -> Option<cmp::Ordering>)
 cmp_impl!(impl Eq, )
 cmp_impl!(impl Ord, cmp -> cmp::Ordering)
 
index 054a97315add0fa083a95ea4ce6065978c96a4d1..675b2e507b3e9073448bfc99dc6369c53b39ed27 100644 (file)
@@ -55,12 +55,12 @@ pub enum Identifier {
 
 impl cmp::PartialOrd for Identifier {
     #[inline]
-    fn lt(&self, other: &Identifier) -> bool {
+    fn partial_cmp(&self, other: &Identifier) -> Option<Ordering> {
         match (self, other) {
-            (&Numeric(a), &Numeric(b)) => a < b,
-            (&Numeric(_), _) => true,
-            (&AlphaNumeric(ref a), &AlphaNumeric(ref b)) => *a < *b,
-            (&AlphaNumeric(_), _) => false
+            (&Numeric(a), &Numeric(ref b)) => a.partial_cmp(b),
+            (&Numeric(_), _) => Some(Less),
+            (&AlphaNumeric(ref a), &AlphaNumeric(ref b)) => a.partial_cmp(b),
+            (&AlphaNumeric(_), _) => Some(Greater)
         }
     }
 }
@@ -130,30 +130,31 @@ fn eq(&self, other: &Version) -> bool {
 
 impl cmp::PartialOrd for Version {
     #[inline]
-    fn lt(&self, other: &Version) -> bool {
-
-        self.major < other.major ||
-
-            (self.major == other.major &&
-             self.minor < other.minor) ||
-
-            (self.major == other.major &&
-             self.minor == other.minor &&
-             self.patch < other.patch) ||
-
-            (self.major == other.major &&
-             self.minor == other.minor &&
-             self.patch == other.patch &&
-             // NB: semver spec says 0.0.0-pre < 0.0.0
-             // but the version of ord defined for vec
-             // says that [] < [pre], so we alter it
-             // here.
-             (match (self.pre.len(), other.pre.len()) {
-                 (0, 0) => false,
-                 (0, _) => false,
-                 (_, 0) => true,
-                 (_, _) => self.pre < other.pre
-             }))
+    fn partial_cmp(&self, other: &Version) -> Option<Ordering> {
+        match self.major.partial_cmp(&other.major) {
+            Some(Equal) => {}
+            r => return r,
+        }
+
+        match self.minor.partial_cmp(&other.minor) {
+            Some(Equal) => {}
+            r => return r,
+        }
+
+        match self.patch.partial_cmp(&other.patch) {
+            Some(Equal) => {}
+            r => return r,
+        }
+
+        // NB: semver spec says 0.0.0-pre < 0.0.0
+        // but the version of ord defined for vec
+        // says that [] < [pre] so we alter it here
+        match (self.pre.len(), other.pre.len()) {
+            (0, 0) => Some(Equal),
+            (0, _) => Some(Greater),
+            (_, 0) => Some(Less),
+            (_, _) => self.pre.partial_cmp(&other.pre)
+        }
     }
 }
 
index d8dd2938b34f63d0d5795fd8e01e327434eeddbe..9f5f020152f9e17d8bebf1fe9a2654dbc6e00c60 100644 (file)
@@ -244,7 +244,7 @@ fn main() {
 use Encodable;
 
 /// Represents a json value
-#[deriving(Clone, PartialEq)]
+#[deriving(Clone, PartialEq, PartialOrd)]
 pub enum Json {
     Number(f64),
     String(String),
@@ -2087,62 +2087,6 @@ fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T
     }
 }
 
-/// Test if two json values are less than one another
-impl PartialOrd for Json {
-    fn lt(&self, other: &Json) -> bool {
-        match *self {
-            Number(f0) => {
-                match *other {
-                    Number(f1) => f0 < f1,
-                    String(_) | Boolean(_) | List(_) | Object(_) |
-                    Null => true
-                }
-            }
-
-            String(ref s0) => {
-                match *other {
-                    Number(_) => false,
-                    String(ref s1) => s0 < s1,
-                    Boolean(_) | List(_) | Object(_) | Null => true
-                }
-            }
-
-            Boolean(b0) => {
-                match *other {
-                    Number(_) | String(_) => false,
-                    Boolean(b1) => b0 < b1,
-                    List(_) | Object(_) | Null => true
-                }
-            }
-
-            List(ref l0) => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) => false,
-                    List(ref l1) => (*l0) < (*l1),
-                    Object(_) | Null => true
-                }
-            }
-
-            Object(ref d0) => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) | List(_) => false,
-                    Object(ref d1) => d0 < d1,
-                    Null => true
-                }
-            }
-
-            Null => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) | List(_) |
-                    Object(_) =>
-                        false,
-                    Null => true
-                }
-            }
-        }
-    }
-}
-
 /// A trait for converting values to JSON
 pub trait ToJson {
     /// Converts the value of `self` to an instance of JSON
index 44988a23070d7ce68a7d13bc1a9cebf79ecc14f8..80f1cbe6cb29e3bcdc07836c4c347bebef525f7d 100644 (file)
@@ -24,6 +24,7 @@
 use fmt;
 use hash;
 use kinds::marker;
+use option::Option;
 use ops::Deref;
 use raw;
 
@@ -58,6 +59,10 @@ fn eq(&self, other: &Gc<T>) -> bool { *(*self) == *(*other) }
     fn ne(&self, other: &Gc<T>) -> bool { *(*self) != *(*other) }
 }
 impl<T: PartialOrd + 'static> PartialOrd for Gc<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &Gc<T>) -> Option<Ordering> {
+        (**self).partial_cmp(&**other)
+    }
     #[inline]
     fn lt(&self, other: &Gc<T>) -> bool { *(*self) < *(*other) }
     #[inline]
index 88ebe8a60faff5370bfacb7a1b5e025099d8add5..59cdec1ea88f07f240ad27aca105053111f6b475 100644 (file)
@@ -43,22 +43,116 @@ macro_rules! md (
         } }
     );
 
+    let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"]));
+    let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"],
+                                    None,
+                                    vec![box ordering_ty],
+                                    true));
+
+    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let attrs = vec!(cx.attribute(span, inline));
+
+    let partial_cmp_def = MethodDef {
+        name: "partial_cmp",
+        generics: LifetimeBounds::empty(),
+        explicit_self: borrowed_explicit_self(),
+        args: vec![borrowed_self()],
+        ret_ty: ret_ty,
+        attributes: attrs,
+        const_nonmatching: false,
+        combine_substructure: combine_substructure(|cx, span, substr| {
+            cs_partial_cmp(cx, span, substr)
+        })
+    };
+
     let trait_def = TraitDef {
         span: span,
-        attributes: Vec::new(),
-        path: Path::new(vec!("std", "cmp", "PartialOrd")),
-        additional_bounds: Vec::new(),
+        attributes: vec![],
+        path: Path::new(vec!["std", "cmp", "PartialOrd"]),
+        additional_bounds: vec![],
         generics: LifetimeBounds::empty(),
-        methods: vec!(
+        methods: vec![
+            partial_cmp_def,
             md!("lt", true, false),
             md!("le", true, true),
             md!("gt", false, false),
             md!("ge", false, true)
-        )
+        ]
     };
     trait_def.expand(cx, mitem, item, push)
 }
 
+pub fn some_ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> Gc<ast::Expr> {
+    let cnst = match cnst {
+        Less => "Less",
+        Equal => "Equal",
+        Greater => "Greater"
+    };
+    let ordering = cx.path_global(span,
+                                  vec!(cx.ident_of("std"),
+                                       cx.ident_of("cmp"),
+                                       cx.ident_of(cnst)));
+    let ordering = cx.expr_path(ordering);
+    cx.expr_some(span, ordering)
+}
+
+pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
+              substr: &Substructure) -> Gc<Expr> {
+    let test_id = cx.ident_of("__test");
+    let equals_expr = some_ordering_const(cx, span, Equal);
+
+    /*
+    Builds:
+
+    let __test = self_field1.partial_cmp(&other_field2);
+    if __test == ::std::option::Some(::std::cmp::Equal) {
+        let __test = self_field2.partial_cmp(&other_field2);
+        if __test == ::std::option::Some(::std::cmp::Equal) {
+            ...
+        } else {
+            __test
+        }
+    } else {
+        __test
+    }
+
+    FIXME #6449: These `if`s could/should be `match`es.
+    */
+    cs_same_method_fold(
+        // foldr nests the if-elses correctly, leaving the first field
+        // as the outermost one, and the last as the innermost.
+        false,
+        |cx, span, old, new| {
+            // let __test = new;
+            // if __test == Some(::std::cmp::Equal) {
+            //    old
+            // } else {
+            //    __test
+            // }
+
+            let assign = cx.stmt_let(span, false, test_id, new);
+
+            let cond = cx.expr_binary(span, ast::BiEq,
+                                      cx.expr_ident(span, test_id),
+                                      equals_expr.clone());
+            let if_ = cx.expr_if(span,
+                                 cond,
+                                 old, Some(cx.expr_ident(span, test_id)));
+            cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
+        },
+        equals_expr.clone(),
+        |cx, span, list, _| {
+            match list {
+                // an earlier nonmatching variant is Less than a
+                // later one.
+                [(self_var, _, _), (other_var, _, _)] =>
+                     some_ordering_const(cx, span, self_var.cmp(&other_var)),
+                _ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
+            }
+        },
+        cx, span, substr)
+}
+
 /// Strict inequality.
 fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span,
          substr: &Substructure) -> Gc<Expr> {
index 077286eef499b7ec867c3bc6a21492a8d0592359..dd6c11d2b39932b2846af2c42fc0ec2902160105 100644 (file)
@@ -27,6 +27,7 @@ enum Enum {
 //~^^^^^ ERROR
 //~^^^^^^ ERROR
 //~^^^^^^^ ERROR
+//~^^^^^^^^ ERROR
    }
 }
 
index 8fd4ba6053e22b63b1c671a3e321b66f95603ed8..1b3d73a6f8bee9381534fe2ca11bd57e926a9a78 100644 (file)
@@ -27,6 +27,7 @@ enum Enum {
 //~^^^^^ ERROR
 //~^^^^^^ ERROR
 //~^^^^^^^ ERROR
+//~^^^^^^^^ ERROR
      )
 }
 
index 3a198a542e4ad15d0ba4c342ee9332b02ba5a645..2ef3b4dfe8a2f1218bc8e2ad19665713f8a4fbbf 100644 (file)
@@ -26,6 +26,7 @@ struct Struct {
 //~^^^^^ ERROR
 //~^^^^^^ ERROR
 //~^^^^^^^ ERROR
+//~^^^^^^^^ ERROR
 }
 
 fn main() {}
index 2de3c18425b5775670d07cb4ea5875d3fb1591cd..303896737dc28183ec4123cfafc036c2d5164db1 100644 (file)
@@ -26,6 +26,7 @@ struct Struct(
 //~^^^^^ ERROR
 //~^^^^^^ ERROR
 //~^^^^^^^ ERROR
+//~^^^^^^^^ ERROR
 );
 
 fn main() {}
index d6fe83a77032bd80b1e31a2f60c4b55d9586f4ef..293f372866d1097ea62b9348b65f4ff9a768ce05 100644 (file)
@@ -10,7 +10,7 @@
 
 #[deriving(PartialEq)]
 struct thing(uint);
-impl PartialOrd for thing { //~ ERROR not all trait methods implemented, missing: `lt`
+impl PartialOrd for thing { //~ ERROR not all trait methods implemented, missing: `partial_cmp`
     fn le(&self, other: &thing) -> bool { true }
     fn ge(&self, other: &thing) -> bool { true }
 }
index 7805a2bb49e80e9d7af00dd695c5532268c910db..cfba87c3f6994aef1b7795847f94bab737859796 100644 (file)
@@ -31,10 +31,10 @@ fn eq(&self, other: &Int) -> bool {
 }
 
 impl PartialOrd for Int {
-    fn lt(&self, other: &Int) -> bool {
+    fn partial_cmp(&self, other: &Int) -> Option<Ordering> {
         let Int(this) = *self;
         let Int(other) = *other;
-        this < other
+        this.partial_cmp(&other)
     }
 }
 
@@ -49,10 +49,10 @@ fn eq(&self, other: &RevInt) -> bool {
 }
 
 impl PartialOrd for RevInt {
-    fn lt(&self, other: &RevInt) -> bool {
+    fn partial_cmp(&self, other: &RevInt) -> Option<Ordering> {
         let RevInt(this) = *self;
         let RevInt(other) = *other;
-        this > other
+        other.partial_cmp(&this)
     }
 }
 
index 69ee47fd1d946e4ea97cf8a1814eb09d391a6a9d..df5c58ff04b6d7f8cc8c0c7dad5bc9f9c86f35b9 100644 (file)
@@ -18,7 +18,7 @@ fn eq(&self, _: &FailCmp) -> bool { fail!("eq") }
 }
 
 impl PartialOrd for FailCmp {
-    fn lt(&self, _: &FailCmp) -> bool { fail!("lt") }
+    fn partial_cmp(&self, _: &FailCmp) -> Option<Ordering> { fail!("partial_cmp") }
 }
 
 impl Eq for FailCmp {}