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:
commit
e549b80e3c
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user