auto merge of #5587 : thestinger/rust/total, r=pcwalton

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`.
This commit is contained in:
bors 2013-03-28 02:36:49 -07:00
commit e549b80e3c
5 changed files with 137 additions and 77 deletions

View File

@ -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.
//
@ -21,15 +21,13 @@ 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 {
@ -37,70 +35,68 @@ pub trait Eq {
fn ne(&self, other: &Self) -> bool;
}
/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
pub trait TotalEq {
fn equals(&self, other: &Self) -> bool;
}
macro_rules! totaleq_impl(
($t:ty) => {
impl TotalEq for $t {
#[inline(always)]
fn equals(&self, other: &$t) -> bool { *self == *other }
}
}
)
totaleq_impl!(bool)
totaleq_impl!(u8)
totaleq_impl!(u16)
totaleq_impl!(u32)
totaleq_impl!(u64)
totaleq_impl!(i8)
totaleq_impl!(i16)
totaleq_impl!(i32)
totaleq_impl!(i64)
totaleq_impl!(int)
totaleq_impl!(uint)
#[deriving(Eq)]
pub enum Ordering { Less, Equal, Greater }
/// Trait for types that form a total order
pub trait TotalOrd {
pub trait TotalOrd: TotalEq {
fn cmp(&self, other: &Self) -> Ordering;
}
#[inline(always)]
fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
if *a < *b { Less }
else if *a > *b { Greater }
else { Equal }
}
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 u8 {
#[inline(always)]
fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
}
totalord_impl!(u8)
totalord_impl!(u16)
totalord_impl!(u32)
totalord_impl!(u64)
impl TotalOrd for u16 {
#[inline(always)]
fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
}
totalord_impl!(i8)
totalord_impl!(i16)
totalord_impl!(i32)
totalord_impl!(i64)
impl TotalOrd for u32 {
#[inline(always)]
fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) }
}
impl TotalOrd for u64 {
#[inline(always)]
fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) }
}
impl TotalOrd for i8 {
#[inline(always)]
fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) }
}
impl TotalOrd for i16 {
#[inline(always)]
fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) }
}
impl TotalOrd for i32 {
#[inline(always)]
fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) }
}
impl TotalOrd for i64 {
#[inline(always)]
fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) }
}
impl TotalOrd for int {
#[inline(always)]
fn cmp(&self, other: &int) -> Ordering { icmp(self, other) }
}
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.
@ -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));
}
}

View File

@ -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.
//
@ -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 () {
@ -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 }
}

View File

@ -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};

View File

@ -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;
@ -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)]

View File

@ -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;
@ -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; }
@ -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) }
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 equals(&self, other: &@[T]) -> bool { equals(*self, *other) }
}
#[cfg(notest)]