Skip to content

Commit

Permalink
create a sensible comparison trait hierarchy
Browse files Browse the repository at this point in the history
* `Ord` inherits from `Eq`
* `TotalOrd` inherits from `TotalEq`
* `TotalOrd` inherits from `Ord`
* `TotalEq` inherits from `Eq`

This is a partial implementation of #12517.
  • Loading branch information
thestinger committed Mar 8, 2014
1 parent 33768c4 commit 4d7d101
Show file tree
Hide file tree
Showing 29 changed files with 156 additions and 53 deletions.
71 changes: 71 additions & 0 deletions src/libcollections/btree.rs
Expand Up @@ -92,6 +92,11 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for BTree<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for BTree<K, V> {
fn eq(&self, other: &BTree<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for BTree<K, V> {
///Testing equality on BTrees by comparing the root.
Expand All @@ -100,6 +105,12 @@ impl<K: TotalOrd, V: TotalEq> TotalEq for BTree<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Ord for BTree<K, V> {
fn lt(&self, other: &BTree<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for BTree<K, V> {
///Returns an ordering based on the root nodes of each BTree.
fn cmp(&self, other: &BTree<K, V>) -> Ordering {
Expand Down Expand Up @@ -191,6 +202,12 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for Node<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for Node<K, V> {
fn eq(&self, other: &Node<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for Node<K, V> {
///Returns whether two nodes are equal based on the keys of each element.
///Two nodes are equal if all of their keys are the same.
Expand All @@ -215,6 +232,12 @@ impl<K: TotalOrd, V: TotalEq> TotalEq for Node<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Ord for Node<K, V> {
fn lt(&self, other: &Node<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for Node<K, V> {
///Implementation of TotalOrd for Nodes.
fn cmp(&self, other: &Node<K, V>) -> Ordering {
Expand Down Expand Up @@ -380,13 +403,25 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for Leaf<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for Leaf<K, V> {
fn eq(&self, other: &Leaf<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for Leaf<K, V> {
///Implementation of equals function for leaves that compares LeafElts.
fn equals(&self, other: &Leaf<K, V>) -> bool {
self.elts.equals(&other.elts)
}
}

impl<K: TotalOrd, V: TotalEq> Ord for Leaf<K, V> {
fn lt(&self, other: &Leaf<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for Leaf<K, V> {
///Returns an ordering based on the first element of each Leaf.
fn cmp(&self, other: &Leaf<K, V>) -> Ordering {
Expand Down Expand Up @@ -602,13 +637,25 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for Branch<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for Branch<K, V> {
fn eq(&self, other: &Branch<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for Branch<K, V> {
///Equals function for Branches--compares all the elements in each branch
fn equals(&self, other: &Branch<K, V>) -> bool {
self.elts.equals(&other.elts)
}
}

impl<K: TotalOrd, V: TotalEq> Ord for Branch<K, V> {
fn lt(&self, other: &Branch<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for Branch<K, V> {
///Compares the first elements of two branches to determine an ordering
fn cmp(&self, other: &Branch<K, V>) -> Ordering {
Expand Down Expand Up @@ -663,13 +710,25 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for LeafElt<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for LeafElt<K, V> {
fn eq(&self, other: &LeafElt<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for LeafElt<K, V> {
///TotalEq for LeafElts
fn equals(&self, other: &LeafElt<K, V>) -> bool {
self.key.equals(&other.key) && self.value.equals(&other.value)
}
}

impl<K: TotalOrd, V: TotalEq> Ord for LeafElt<K, V> {
fn lt(&self, other: &LeafElt<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for LeafElt<K, V> {
///Returns an ordering based on the keys of the LeafElts.
fn cmp(&self, other: &LeafElt<K, V>) -> Ordering {
Expand Down Expand Up @@ -705,13 +764,25 @@ impl<K: Clone + TotalOrd, V: Clone> Clone for BranchElt<K, V> {
}
}

impl<K: TotalOrd, V: TotalEq> Eq for BranchElt<K, V>{
fn eq(&self, other: &BranchElt<K, V>) -> bool {
self.equals(other)
}
}

impl<K: TotalOrd, V: TotalEq> TotalEq for BranchElt<K, V>{
///TotalEq for BranchElts
fn equals(&self, other: &BranchElt<K, V>) -> bool {
self.key.equals(&other.key)&&self.value.equals(&other.value)
}
}

impl<K: TotalOrd, V: TotalEq> Ord for BranchElt<K, V> {
fn lt(&self, other: &BranchElt<K, V>) -> bool {
self.cmp(other) == Less
}
}

impl<K: TotalOrd, V: TotalEq> TotalOrd for BranchElt<K, V> {
///Fulfills TotalOrd for BranchElts
fn cmp(&self, other: &BranchElt<K, V>) -> Ordering {
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/dlist.rs
Expand Up @@ -607,7 +607,7 @@ impl<A: Eq> Eq for DList<A> {
}
}

impl<A: Eq + Ord> Ord for DList<A> {
impl<A: Ord> Ord for DList<A> {
fn lt(&self, other: &DList<A>) -> bool {
iter::order::lt(self.iter(), other.iter())
}
Expand Down
2 changes: 1 addition & 1 deletion src/libextra/workcache.rs
Expand Up @@ -88,7 +88,7 @@ use std::io::{File, MemWriter};
*
*/

#[deriving(Clone, Eq, Encodable, Decodable, TotalOrd, TotalEq)]
#[deriving(Clone, Eq, Encodable, Decodable, Ord, TotalOrd, TotalEq)]
struct WorkKey {
kind: ~str,
name: ~str
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/back/link.rs
Expand Up @@ -46,7 +46,7 @@ use syntax::attr::AttrMetaMethods;
use syntax::crateid::CrateId;
use syntax::parse::token;

#[deriving(Clone, Eq, TotalOrd, TotalEq)]
#[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)]
pub enum OutputType {
OutputTypeBitcode,
OutputTypeAssembly,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/driver/session.rs
Expand Up @@ -166,7 +166,7 @@ pub enum EntryFnType {
EntryNone,
}

#[deriving(Eq, Clone, TotalOrd, TotalEq)]
#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq)]
pub enum CrateType {
CrateTypeExecutable,
CrateTypeDylib,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/const_eval.rs
Expand Up @@ -525,7 +525,7 @@ pub fn lit_to_const(lit: &Lit) -> const_val {
}
}

fn compare_vals<T : Eq + Ord>(a: T, b: T) -> Option<int> {
fn compare_vals<T: Ord>(a: T, b: T) -> Option<int> {
Some(if a == b { 0 } else if a < b { -1 } else { 1 })
}
pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/ty.rs
Expand Up @@ -633,13 +633,13 @@ impl Region {
}
}

#[deriving(Clone, Eq, TotalOrd, TotalEq, Hash, Encodable, Decodable, Show)]
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Hash, Encodable, Decodable, Show)]
pub struct FreeRegion {
scope_id: NodeId,
bound_region: BoundRegion
}

#[deriving(Clone, Eq, TotalEq, TotalOrd, Hash, Encodable, Decodable, Show)]
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Hash, Encodable, Decodable, Show)]
pub enum BoundRegion {
/// An anonymous region parameter for a given fn (&T)
BrAnon(uint),
Expand Down
14 changes: 8 additions & 6 deletions src/libstd/cmp.rs
Expand Up @@ -42,8 +42,12 @@ pub trait Eq {
}

/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
pub trait TotalEq {
fn equals(&self, other: &Self) -> bool;
pub trait TotalEq: Eq {
/// This method must return the same value as `eq`. It exists to prevent
/// deriving `TotalEq` from fields not implementing the `TotalEq` trait.
fn equals(&self, other: &Self) -> bool {
self.eq(other)
}
}

macro_rules! totaleq_impl(
Expand Down Expand Up @@ -76,7 +80,7 @@ totaleq_impl!(char)
pub enum Ordering { Less = -1, Equal = 0, Greater = 1 }

/// Trait for types that form a total order
pub trait TotalOrd: TotalEq {
pub trait TotalOrd: TotalEq + Ord {
fn cmp(&self, other: &Self) -> Ordering;
}

Expand Down Expand Up @@ -161,16 +165,14 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
* (cf. IEEE 754-2008 section 5.11).
*/
#[lang="ord"]
pub trait Ord {
pub trait Ord: Eq {
fn lt(&self, other: &Self) -> bool;
#[inline]
fn le(&self, other: &Self) -> bool { !other.lt(self) }
#[inline]
fn gt(&self, other: &Self) -> bool { other.lt(self) }
#[inline]
fn ge(&self, other: &Self) -> bool { !self.lt(other) }

// FIXME (#12068): Add min/max/clamp default methods
}

/// The equivalence relation. Two values may be equivalent even if they are
Expand Down
16 changes: 11 additions & 5 deletions src/libstd/iter.rs
Expand Up @@ -2033,7 +2033,7 @@ pub fn range_inclusive<A: Add<A, A> + Ord + Clone + One + ToPrimitive>(start: A,
RangeInclusive{range: range(start, stop), done: false}
}

impl<A: Add<A, A> + Eq + Ord + Clone + ToPrimitive> Iterator<A> for RangeInclusive<A> {
impl<A: Add<A, A> + Ord + Clone + ToPrimitive> Iterator<A> for RangeInclusive<A> {
#[inline]
fn next(&mut self) -> Option<A> {
match self.range.next() {
Expand Down Expand Up @@ -2244,7 +2244,7 @@ pub mod order {
}

/// Return `a` < `b` lexicographically (Using partial order, `Ord`)
pub fn lt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
pub fn lt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return false,
Expand All @@ -2256,7 +2256,7 @@ pub mod order {
}

/// Return `a` <= `b` lexicographically (Using partial order, `Ord`)
pub fn le<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
pub fn le<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
Expand All @@ -2268,7 +2268,7 @@ pub mod order {
}

/// Return `a` > `b` lexicographically (Using partial order, `Ord`)
pub fn gt<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
pub fn gt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return false,
Expand All @@ -2280,7 +2280,7 @@ pub mod order {
}

/// Return `a` >= `b` lexicographically (Using partial order, `Ord`)
pub fn ge<A: Eq + Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
pub fn ge<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
Expand Down Expand Up @@ -2978,6 +2978,12 @@ mod tests {
}
}

impl Eq for Foo {
fn eq(&self, _: &Foo) -> bool {
true
}
}

impl Ord for Foo {
fn lt(&self, _: &Foo) -> bool {
false
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/option.rs
Expand Up @@ -40,7 +40,7 @@
use any::Any;
use clone::Clone;
use clone::DeepClone;
use cmp::{Eq, TotalEq, TotalOrd};
use cmp::{Eq, TotalOrd};
use default::Default;
use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize};
use kinds::Send;
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/vec.rs
Expand Up @@ -682,7 +682,7 @@ pub mod traits {
fn cmp(&self, other: &~[T]) -> Ordering { self.as_slice().cmp(&other.as_slice()) }
}

impl<'a, T: Eq + Ord> Ord for &'a [T] {
impl<'a, T: Ord> Ord for &'a [T] {
fn lt(&self, other: & &'a [T]) -> bool {
order::lt(self.iter(), other.iter())
}
Expand All @@ -700,7 +700,7 @@ pub mod traits {
}
}

impl<T: Eq + Ord> Ord for ~[T] {
impl<T: Ord> Ord for ~[T] {
#[inline]
fn lt(&self, other: &~[T]) -> bool { self.as_slice() < other.as_slice() }
#[inline]
Expand Down
15 changes: 11 additions & 4 deletions src/libstd/vec_ng.rs
Expand Up @@ -13,7 +13,7 @@

use cast::{forget, transmute};
use clone::Clone;
use cmp::{Eq, Ordering, TotalEq, TotalOrd};
use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd};
use container::Container;
use default::Default;
use fmt;
Expand Down Expand Up @@ -136,21 +136,28 @@ impl<T> Extendable<T> for Vec<T> {
}
}

impl<T:Eq> Eq for Vec<T> {
impl<T: Eq> Eq for Vec<T> {
#[inline]
fn eq(&self, other: &Vec<T>) -> bool {
self.as_slice() == other.as_slice()
}
}

impl<T:TotalEq> TotalEq for Vec<T> {
impl<T: Ord> Ord for Vec<T> {
#[inline]
fn lt(&self, other: &Vec<T>) -> bool {
self.as_slice() < other.as_slice()
}
}

impl<T: TotalEq> TotalEq for Vec<T> {
#[inline]
fn equals(&self, other: &Vec<T>) -> bool {
self.as_slice().equals(&other.as_slice())
}
}

impl<T:TotalOrd> TotalOrd for Vec<T> {
impl<T: TotalOrd> TotalOrd for Vec<T> {
#[inline]
fn cmp(&self, other: &Vec<T>) -> Ordering {
self.as_slice().cmp(&other.as_slice())
Expand Down

5 comments on commit 4d7d101

@bors
Copy link
Contributor

@bors bors commented on 4d7d101 Mar 8, 2014

Choose a reason for hiding this comment

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

@bors
Copy link
Contributor

@bors bors commented on 4d7d101 Mar 8, 2014

Choose a reason for hiding this comment

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

merging thestinger/rust/cmp = 4d7d101 into auto

@bors
Copy link
Contributor

@bors bors commented on 4d7d101 Mar 8, 2014

Choose a reason for hiding this comment

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

thestinger/rust/cmp = 4d7d101 merged ok, testing candidate = 96e8c00

@bors
Copy link
Contributor

@bors bors commented on 4d7d101 Mar 8, 2014

Choose a reason for hiding this comment

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

@bors
Copy link
Contributor

@bors bors commented on 4d7d101 Mar 8, 2014

Choose a reason for hiding this comment

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

fast-forwarding master to auto = 96e8c00

Please sign in to comment.