Skip to content

Implement RFC#28: Add PartialOrd::partial_cmp #15030

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 1 commit into from
Jun 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions src/liballoc/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use core::fmt;
use core::intrinsics;
use core::kinds::Send;
use core::mem;
use core::option::Option;
use core::raw::TraitObject;
use core::result::{Ok, Err, Result};

Expand Down Expand Up @@ -64,6 +65,10 @@ impl<T:PartialEq> PartialEq for Box<T> {
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]
Expand Down
5 changes: 5 additions & 0 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ impl<T: PartialEq> PartialEq for Rc<T> {
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 }

Expand Down
24 changes: 12 additions & 12 deletions src/libcollections/btree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ impl<K: Ord, V: Eq> PartialEq for BTree<K, V> {
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))
}
}

Expand Down Expand Up @@ -229,8 +229,8 @@ impl<K: Ord, V: Eq> PartialEq for Node<K, V> {
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))
}
}

Expand Down Expand Up @@ -408,8 +408,8 @@ impl<K: Ord, V: Eq> PartialEq for Leaf<K, V> {
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))
}
}

Expand Down Expand Up @@ -638,8 +638,8 @@ impl<K: Ord, V: Eq> PartialEq for Branch<K, V> {
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))
}
}

Expand Down Expand Up @@ -706,8 +706,8 @@ impl<K: Ord, V: Eq> PartialEq for LeafElt<K, V> {
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))
}
}

Expand Down Expand Up @@ -755,8 +755,8 @@ impl<K: Ord, V: Eq> PartialEq for BranchElt<K, V>{
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))
}
}

Expand Down
13 changes: 2 additions & 11 deletions src/libcollections/dlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,17 +595,8 @@ impl<A: PartialEq> PartialEq for DList<A> {
}

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())
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}

Expand Down
26 changes: 8 additions & 18 deletions src/libcollections/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,11 @@ impl<K: PartialEq + Ord, V: PartialEq> PartialEq for TreeMap<K, V> {
}
}

// 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> {
Expand Down Expand Up @@ -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> {
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,8 @@ impl<T: PartialEq> PartialEq for Vec<T> {

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())
}
}

Expand Down
81 changes: 72 additions & 9 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
//! 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
Expand Down Expand Up @@ -127,7 +131,9 @@ impl Ord for 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.
Expand All @@ -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
Expand All @@ -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)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, why does this need staging?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snapshot's deriving won't generate partial_cmp so there needs to be a default impl.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, tricky!

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
Expand Down Expand Up @@ -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)*) => ($(
Expand Down Expand Up @@ -227,6 +271,15 @@ mod impls {
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]
Expand All @@ -241,13 +294,15 @@ mod impls {

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))
}
}

Expand Down Expand Up @@ -288,6 +343,10 @@ mod impls {
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]
Expand All @@ -311,6 +370,10 @@ mod impls {
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]
Expand Down
18 changes: 17 additions & 1 deletion src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,7 @@ impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
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`
Expand Down Expand Up @@ -2212,6 +2212,22 @@ pub mod order {
}
}

/// 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 {
Expand Down
Loading