Skip to content

Commit e1683f5

Browse files
committed
auto merge of #15030 : sfackler/rust/partial-cmp, r=huonw
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`. # Note This isn't ready to merge yet since libcore tests are broken as you end up with 2 versions of `Option`. The rest should be reviewable though. RFC: 0028-partial-cmp
2 parents e25eb6b + 55cae0a commit e1683f5

28 files changed

+346
-164
lines changed

src/liballoc/owned.rs

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use core::fmt;
1818
use core::intrinsics;
1919
use core::kinds::Send;
2020
use core::mem;
21+
use core::option::Option;
2122
use core::raw::TraitObject;
2223
use core::result::{Ok, Err, Result};
2324

@@ -64,6 +65,10 @@ impl<T:PartialEq> PartialEq for Box<T> {
6465
fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
6566
}
6667
impl<T:PartialOrd> PartialOrd for Box<T> {
68+
#[inline]
69+
fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
70+
(**self).partial_cmp(*other)
71+
}
6772
#[inline]
6873
fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
6974
#[inline]

src/liballoc/rc.rs

+5
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ impl<T: PartialEq> PartialEq for Rc<T> {
170170
impl<T: Eq> Eq for Rc<T> {}
171171

172172
impl<T: PartialOrd> PartialOrd for Rc<T> {
173+
#[inline(always)]
174+
fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
175+
(**self).partial_cmp(&**other)
176+
}
177+
173178
#[inline(always)]
174179
fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
175180

src/libcollections/btree.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ impl<K: Ord, V: Eq> PartialEq for BTree<K, V> {
107107
impl<K: Ord, V: Eq> Eq for BTree<K, V> {}
108108

109109
impl<K: Ord, V: Eq> PartialOrd for BTree<K, V> {
110-
fn lt(&self, other: &BTree<K, V>) -> bool {
111-
self.cmp(other) == Less
110+
fn partial_cmp(&self, other: &BTree<K, V>) -> Option<Ordering> {
111+
Some(self.cmp(other))
112112
}
113113
}
114114

@@ -229,8 +229,8 @@ impl<K: Ord, V: Eq> PartialEq for Node<K, V> {
229229
impl<K: Ord, V: Eq> Eq for Node<K, V> {}
230230

231231
impl<K: Ord, V: Eq> PartialOrd for Node<K, V> {
232-
fn lt(&self, other: &Node<K, V>) -> bool {
233-
self.cmp(other) == Less
232+
fn partial_cmp(&self, other: &Node<K, V>) -> Option<Ordering> {
233+
Some(self.cmp(other))
234234
}
235235
}
236236

@@ -408,8 +408,8 @@ impl<K: Ord, V: Eq> PartialEq for Leaf<K, V> {
408408
impl<K: Ord, V: Eq> Eq for Leaf<K, V> {}
409409

410410
impl<K: Ord, V: Eq> PartialOrd for Leaf<K, V> {
411-
fn lt(&self, other: &Leaf<K, V>) -> bool {
412-
self.cmp(other) == Less
411+
fn partial_cmp(&self, other: &Leaf<K, V>) -> Option<Ordering> {
412+
Some(self.cmp(other))
413413
}
414414
}
415415

@@ -638,8 +638,8 @@ impl<K: Ord, V: Eq> PartialEq for Branch<K, V> {
638638
impl<K: Ord, V: Eq> Eq for Branch<K, V> {}
639639

640640
impl<K: Ord, V: Eq> PartialOrd for Branch<K, V> {
641-
fn lt(&self, other: &Branch<K, V>) -> bool {
642-
self.cmp(other) == Less
641+
fn partial_cmp(&self, other: &Branch<K, V>) -> Option<Ordering> {
642+
Some(self.cmp(other))
643643
}
644644
}
645645

@@ -706,8 +706,8 @@ impl<K: Ord, V: Eq> PartialEq for LeafElt<K, V> {
706706
impl<K: Ord, V: Eq> Eq for LeafElt<K, V> {}
707707

708708
impl<K: Ord, V: Eq> PartialOrd for LeafElt<K, V> {
709-
fn lt(&self, other: &LeafElt<K, V>) -> bool {
710-
self.cmp(other) == Less
709+
fn partial_cmp(&self, other: &LeafElt<K, V>) -> Option<Ordering> {
710+
Some(self.cmp(other))
711711
}
712712
}
713713

@@ -755,8 +755,8 @@ impl<K: Ord, V: Eq> PartialEq for BranchElt<K, V>{
755755
impl<K: Ord, V: Eq> Eq for BranchElt<K, V>{}
756756

757757
impl<K: Ord, V: Eq> PartialOrd for BranchElt<K, V> {
758-
fn lt(&self, other: &BranchElt<K, V>) -> bool {
759-
self.cmp(other) == Less
758+
fn partial_cmp(&self, other: &BranchElt<K, V>) -> Option<Ordering> {
759+
Some(self.cmp(other))
760760
}
761761
}
762762

src/libcollections/dlist.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -595,17 +595,8 @@ impl<A: PartialEq> PartialEq for DList<A> {
595595
}
596596

597597
impl<A: PartialOrd> PartialOrd for DList<A> {
598-
fn lt(&self, other: &DList<A>) -> bool {
599-
iter::order::lt(self.iter(), other.iter())
600-
}
601-
fn le(&self, other: &DList<A>) -> bool {
602-
iter::order::le(self.iter(), other.iter())
603-
}
604-
fn gt(&self, other: &DList<A>) -> bool {
605-
iter::order::gt(self.iter(), other.iter())
606-
}
607-
fn ge(&self, other: &DList<A>) -> bool {
608-
iter::order::ge(self.iter(), other.iter())
598+
fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
599+
iter::order::partial_cmp(self.iter(), other.iter())
609600
}
610601
}
611602

src/libcollections/str.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,8 @@ impl<'a> Eq for MaybeOwned<'a> {}
572572

573573
impl<'a> PartialOrd for MaybeOwned<'a> {
574574
#[inline]
575-
fn lt(&self, other: &MaybeOwned) -> bool {
576-
self.as_slice().lt(&other.as_slice())
575+
fn partial_cmp(&self, other: &MaybeOwned) -> Option<Ordering> {
576+
Some(self.cmp(other))
577577
}
578578
}
579579

src/libcollections/treemap.rs

+8-18
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,11 @@ impl<K: PartialEq + Ord, V: PartialEq> PartialEq for TreeMap<K, V> {
5656
}
5757
}
5858

59-
// Lexicographical comparison
60-
fn lt<K: PartialOrd + Ord, V: PartialOrd>(a: &TreeMap<K, V>,
61-
b: &TreeMap<K, V>) -> bool {
62-
// the Zip iterator is as long as the shortest of a and b.
63-
for ((key_a, value_a), (key_b, value_b)) in a.iter().zip(b.iter()) {
64-
if *key_a < *key_b { return true; }
65-
if *key_a > *key_b { return false; }
66-
if *value_a < *value_b { return true; }
67-
if *value_a > *value_b { return false; }
68-
}
69-
70-
a.len() < b.len()
71-
}
72-
73-
impl<K: PartialOrd + Ord, V: PartialOrd> PartialOrd for TreeMap<K, V> {
59+
impl<K: Ord, V: PartialOrd> PartialOrd for TreeMap<K, V> {
7460
#[inline]
75-
fn lt(&self, other: &TreeMap<K, V>) -> bool { lt(self, other) }
61+
fn partial_cmp(&self, other: &TreeMap<K, V>) -> Option<Ordering> {
62+
iter::order::partial_cmp(self.iter(), other.iter())
63+
}
7664
}
7765

7866
impl<K: Ord + Show, V: Show> Show for TreeMap<K, V> {
@@ -568,9 +556,11 @@ impl<T: PartialEq + Ord> PartialEq for TreeSet<T> {
568556
fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
569557
}
570558

571-
impl<T: PartialOrd + Ord> PartialOrd for TreeSet<T> {
559+
impl<T: Ord> PartialOrd for TreeSet<T> {
572560
#[inline]
573-
fn lt(&self, other: &TreeSet<T>) -> bool { self.map < other.map }
561+
fn partial_cmp(&self, other: &TreeSet<T>) -> Option<Ordering> {
562+
self.map.partial_cmp(&other.map)
563+
}
574564
}
575565

576566
impl<T: Ord + Show> Show for TreeSet<T> {

src/libcollections/vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ impl<T: PartialEq> PartialEq for Vec<T> {
389389

390390
impl<T: PartialOrd> PartialOrd for Vec<T> {
391391
#[inline]
392-
fn lt(&self, other: &Vec<T>) -> bool {
393-
self.as_slice() < other.as_slice()
392+
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
393+
self.as_slice().partial_cmp(&other.as_slice())
394394
}
395395
}
396396

src/libcore/cmp.rs

+72-9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
//! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
3838
//! ```
3939
40+
use option::{Option, Some};
41+
#[cfg(stage0)]
42+
use option::None;
43+
4044
/// Trait for values that can be compared for equality and inequality.
4145
///
4246
/// This trait allows for partial equality, for types that do not have an
@@ -127,7 +131,9 @@ impl Ord for Ordering {
127131

128132
impl PartialOrd for Ordering {
129133
#[inline]
130-
fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
134+
fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
135+
(*self as int).partial_cmp(&(*other as int))
136+
}
131137
}
132138

133139
/// Combine orderings, lexically.
@@ -145,7 +151,7 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
145151

146152
/// Trait for values that can be compared for a sort-order.
147153
///
148-
/// PartialOrd only requires implementation of the `lt` method,
154+
/// PartialOrd only requires implementation of the `partial_cmp` method,
149155
/// with the others generated from default implementations.
150156
///
151157
/// However it remains possible to implement the others separately for types
@@ -154,20 +160,57 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
154160
/// 5.11).
155161
#[lang="ord"]
156162
pub trait PartialOrd: PartialEq {
163+
/// This method returns an ordering between `self` and `other` values
164+
/// if one exists.
165+
#[cfg(stage0)]
166+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
167+
match (!self.lt(other), !other.lt(self)) {
168+
(false, false) => None,
169+
(false, true) => Some(Less),
170+
(true, false) => Some(Greater),
171+
(true, true) => Some(Equal),
172+
}
173+
}
174+
175+
/// This method returns an ordering between `self` and `other` values
176+
/// if one exists.
177+
#[cfg(not(stage0))]
178+
fn partial_cmp(&self, other: &Self) -> Option<Ordering>;
179+
157180
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
158-
fn lt(&self, other: &Self) -> bool;
181+
fn lt(&self, other: &Self) -> bool {
182+
match self.partial_cmp(other) {
183+
Some(Less) => true,
184+
_ => false,
185+
}
186+
}
159187

160188
/// This method tests less than or equal to (`<=`).
161189
#[inline]
162-
fn le(&self, other: &Self) -> bool { !other.lt(self) }
190+
fn le(&self, other: &Self) -> bool {
191+
match self.partial_cmp(other) {
192+
Some(Less) | Some(Equal) => true,
193+
_ => false,
194+
}
195+
}
163196

164197
/// This method tests greater than (`>`).
165198
#[inline]
166-
fn gt(&self, other: &Self) -> bool { other.lt(self) }
199+
fn gt(&self, other: &Self) -> bool {
200+
match self.partial_cmp(other) {
201+
Some(Greater) => true,
202+
_ => false,
203+
}
204+
}
167205

168206
/// This method tests greater than or equal to (`>=`).
169207
#[inline]
170-
fn ge(&self, other: &Self) -> bool { !self.lt(other) }
208+
fn ge(&self, other: &Self) -> bool {
209+
match self.partial_cmp(other) {
210+
Some(Greater) | Some(Equal) => true,
211+
_ => false,
212+
}
213+
}
171214
}
172215

173216
/// 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 {
195238
mod impls {
196239
use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering,
197240
Less, Greater, Equal};
241+
use option::{Option, Some, None};
198242

199243
macro_rules! eq_impl(
200244
($($t:ty)*) => ($(
@@ -227,6 +271,15 @@ mod impls {
227271
macro_rules! ord_impl(
228272
($($t:ty)*) => ($(
229273
impl PartialOrd for $t {
274+
#[inline]
275+
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
276+
match (self <= other, self >= other) {
277+
(false, false) => None,
278+
(false, true) => Some(Greater),
279+
(true, false) => Some(Less),
280+
(true, true) => Some(Equal),
281+
}
282+
}
230283
#[inline]
231284
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
232285
#[inline]
@@ -241,13 +294,15 @@ mod impls {
241294

242295
impl PartialOrd for () {
243296
#[inline]
244-
fn lt(&self, _other: &()) -> bool { false }
297+
fn partial_cmp(&self, _: &()) -> Option<Ordering> {
298+
Some(Equal)
299+
}
245300
}
246301

247302
impl PartialOrd for bool {
248303
#[inline]
249-
fn lt(&self, other: &bool) -> bool {
250-
(*self as u8) < (*other as u8)
304+
fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
305+
(*self as u8).partial_cmp(&(*other as u8))
251306
}
252307
}
253308

@@ -288,6 +343,10 @@ mod impls {
288343
fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) }
289344
}
290345
impl<'a, T: PartialOrd> PartialOrd for &'a T {
346+
#[inline]
347+
fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
348+
(**self).partial_cmp(*other)
349+
}
291350
#[inline]
292351
fn lt(&self, other: & &'a T) -> bool { *(*self) < *(*other) }
293352
#[inline]
@@ -311,6 +370,10 @@ mod impls {
311370
fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) }
312371
}
313372
impl<'a, T: PartialOrd> PartialOrd for &'a mut T {
373+
#[inline]
374+
fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
375+
(**self).partial_cmp(*other)
376+
}
314377
#[inline]
315378
fn lt(&self, other: &&'a mut T) -> bool { **self < **other }
316379
#[inline]

src/libcore/iter.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -2183,7 +2183,7 @@ impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
21832183
pub mod order {
21842184
use cmp;
21852185
use cmp::{Eq, Ord, PartialOrd, PartialEq};
2186-
use option::{Some, None};
2186+
use option::{Option, Some, None};
21872187
use super::Iterator;
21882188

21892189
/// Compare `a` and `b` for equality using `Eq`
@@ -2212,6 +2212,22 @@ pub mod order {
22122212
}
22132213
}
22142214

2215+
/// Order `a` and `b` lexicographically using `PartialOrd`
2216+
pub fn partial_cmp<A: PartialOrd, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S)
2217+
-> Option<cmp::Ordering> {
2218+
loop {
2219+
match (a.next(), b.next()) {
2220+
(None, None) => return Some(cmp::Equal),
2221+
(None, _ ) => return Some(cmp::Less),
2222+
(_ , None) => return Some(cmp::Greater),
2223+
(Some(x), Some(y)) => match x.partial_cmp(&y) {
2224+
Some(cmp::Equal) => (),
2225+
non_eq => return non_eq,
2226+
},
2227+
}
2228+
}
2229+
}
2230+
22152231
/// Compare `a` and `b` for equality (Using partial equality, `PartialEq`)
22162232
pub fn eq<A: PartialEq, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
22172233
loop {

0 commit comments

Comments
 (0)