Skip to content

Commit

Permalink
auto merge of rust-lang#5587 : thestinger/rust/total, r=pcwalton
Browse files Browse the repository at this point in the history
This is needed so that hash tables can require strict equality but not require types to be ordered. It's a subset of the functionality of `TotalOrd` so I made that inherit from `TotalEq`.
  • Loading branch information
bors committed Mar 28, 2013
2 parents d310532 + d2b267b commit e549b80
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 74 deletions.
124 changes: 63 additions & 61 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -21,86 +21,82 @@ and `Eq` to overload the `==` and `!=` operators.
*/

/**
* Trait for values that can be compared for equality
* and inequality.
* Trait for values that can be compared for equality and inequality.
*
* Eventually this may be simplified to only require
* an `eq` method, with the other generated from
* a default implementation. However it should
* remain possible to implement `ne` separately, for
* compatibility with floating-point NaN semantics
* (cf. IEEE 754-2008 section 5.11).
* This trait allows partial equality, where types can be unordered instead of strictly equal or
* unequal. For example, with the built-in floating-point types `a == b` and `a != b` will both
* evaluate to false if either `a` or `b` is NaN (cf. IEEE 754-2008 section 5.11).
*
* Eventually, this will be implemented by default for types that implement `TotalEq`.
*/
#[lang="eq"]
pub trait Eq {
fn eq(&self, other: &Self) -> bool;
fn ne(&self, other: &Self) -> bool;
}

#[deriving(Eq)]
pub enum Ordering { Less, Equal, Greater }

/// Trait for types that form a total order
pub trait TotalOrd {
fn cmp(&self, other: &Self) -> Ordering;
/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
pub trait TotalEq {
fn equals(&self, other: &Self) -> bool;
}

#[inline(always)]
fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
if *a < *b { Less }
else if *a > *b { Greater }
else { Equal }
}
macro_rules! totaleq_impl(
($t:ty) => {
impl TotalEq for $t {
#[inline(always)]
fn equals(&self, other: &$t) -> bool { *self == *other }
}
}
)

impl TotalOrd for u8 {
#[inline(always)]
fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
}
totaleq_impl!(bool)

impl TotalOrd for u16 {
#[inline(always)]
fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
}
totaleq_impl!(u8)
totaleq_impl!(u16)
totaleq_impl!(u32)
totaleq_impl!(u64)

impl TotalOrd for u32 {
#[inline(always)]
fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) }
}
totaleq_impl!(i8)
totaleq_impl!(i16)
totaleq_impl!(i32)
totaleq_impl!(i64)

impl TotalOrd for u64 {
#[inline(always)]
fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) }
}
totaleq_impl!(int)
totaleq_impl!(uint)

impl TotalOrd for i8 {
#[inline(always)]
fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) }
}
#[deriving(Eq)]
pub enum Ordering { Less, Equal, Greater }

impl TotalOrd for i16 {
#[inline(always)]
fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) }
/// Trait for types that form a total order
pub trait TotalOrd: TotalEq {
fn cmp(&self, other: &Self) -> Ordering;
}

impl TotalOrd for i32 {
#[inline(always)]
fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) }
}
macro_rules! totalord_impl(
($t:ty) => {
impl TotalOrd for $t {
#[inline(always)]
fn cmp(&self, other: &$t) -> Ordering {
if *self < *other { Less }
else if *self > *other { Greater }
else { Equal }
}
}
}
)

impl TotalOrd for i64 {
#[inline(always)]
fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) }
}
totalord_impl!(u8)
totalord_impl!(u16)
totalord_impl!(u32)
totalord_impl!(u64)

impl TotalOrd for int {
#[inline(always)]
fn cmp(&self, other: &int) -> Ordering { icmp(self, other) }
}
totalord_impl!(i8)
totalord_impl!(i16)
totalord_impl!(i32)
totalord_impl!(i64)

impl TotalOrd for uint {
#[inline(always)]
fn cmp(&self, other: &uint) -> Ordering { icmp(self, other) }
}
totalord_impl!(int)
totalord_impl!(uint)

/**
* Trait for values that can be compared for a sort-order.
Expand Down Expand Up @@ -171,11 +167,17 @@ pub fn max<T:Ord>(v1: T, v2: T) -> T {
#[cfg(test)]
mod test {
#[test]
fn test_int() {
fn test_int_totalord() {
assert_eq!(5.cmp(&10), Less);
assert_eq!(10.cmp(&5), Greater);
assert_eq!(5.cmp(&5), Equal);
assert_eq!((-5).cmp(&12), Less);
assert_eq!(12.cmp(-5), Greater);
}

#[test]
fn test_int_totaleq() {
fail_unless!(5.equals(&5));
fail_unless!(!2.equals(&17));
}
}
10 changes: 8 additions & 2 deletions src/libcore/nil.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -15,7 +15,7 @@ Functions for the unit type.
*/

#[cfg(notest)]
use cmp::{Eq, Ord, TotalOrd, Ordering, Equal};
use prelude::*;

#[cfg(notest)]
impl Eq for () {
Expand All @@ -42,3 +42,9 @@ impl TotalOrd for () {
#[inline(always)]
fn cmp(&self, _other: &()) -> Ordering { Equal }
}

#[cfg(notest)]
impl TotalEq for () {
#[inline(always)]
fn equals(&self, _other: &()) -> bool { true }
}
2 changes: 1 addition & 1 deletion src/libcore/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub use result::{Result, Ok, Err};
/* Reexported types and traits */

pub use clone::Clone;
pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
Expand Down
26 changes: 25 additions & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use at_vec;
use cast;
use char;
use clone::Clone;
use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
use cmp::{Equiv, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use libc;
use option::{None, Option, Some};
use ptr;
Expand Down Expand Up @@ -930,6 +930,30 @@ impl Eq for @str {
fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
}
#[cfg(notest)]
impl<'self> TotalEq for &'self str {
#[inline(always)]
fn equals(&self, other: & &'self str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl TotalEq for ~str {
#[inline(always)]
fn equals(&self, other: &~str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl TotalEq for @str {
#[inline(always)]
fn equals(&self, other: &@str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl Ord for ~str {
#[inline(always)]
Expand Down
46 changes: 37 additions & 9 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use container::{Container, Mutable};
use cast;
use cmp::{Eq, Equiv, Ord, TotalOrd, Ordering, Less, Equal, Greater};
use cmp::{Eq, Equiv, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use clone::Clone;
use iter::BaseIter;
use iter;
Expand Down Expand Up @@ -1547,7 +1547,7 @@ pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U {

// Equality

fn eq<T:Eq>(a: &[T], b: &[T]) -> bool {
fn eq<T: Eq>(a: &[T], b: &[T]) -> bool {
let (a_len, b_len) = (a.len(), b.len());
if a_len != b_len { return false; }

Expand All @@ -1556,33 +1556,61 @@ fn eq<T:Eq>(a: &[T], b: &[T]) -> bool {
if a[i] != b[i] { return false; }
i += 1;
}
true
}

fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool {
let (a_len, b_len) = (a.len(), b.len());
if a_len != b_len { return false; }

let mut i = 0;
while i < a_len {
if !a[i].equals(&b[i]) { return false; }
i += 1;
}
true
}

#[cfg(notest)]
impl<'self,T:Eq> Eq for &'self [T] {
#[inline(always)]
fn eq(&self, other: & &'self [T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: & &'self [T]) -> bool { !(*self).eq(other) }
fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) }
}


#[cfg(notest)]
impl<T:Eq> Eq for ~[T] {
#[inline(always)]
fn eq(&self, other: &~[T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: &~[T]) -> bool { !(*self).eq(other) }
fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
}

#[cfg(notest)]
impl<T:Eq> Eq for @[T] {
#[inline(always)]
fn eq(&self, other: &@[T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: &@[T]) -> bool { !self.eq(other) }
}

#[cfg(notest)]
impl<'self,T:TotalEq> TotalEq for &'self [T] {
#[inline(always)]
fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) }
}

#[cfg(notest)]
impl<T:TotalEq> TotalEq for ~[T] {
#[inline(always)]
fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) }
}

#[cfg(notest)]
impl<T:TotalEq> TotalEq for @[T] {
#[inline(always)]
fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) }
fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) }
}

#[cfg(notest)]
Expand Down

0 comments on commit e549b80

Please sign in to comment.