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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// 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
|
* Trait for values that can be compared for equality and inequality.
|
||||||
* and inequality.
|
|
||||||
*
|
*
|
||||||
* Eventually this may be simplified to only require
|
* This trait allows partial equality, where types can be unordered instead of strictly equal or
|
||||||
* an `eq` method, with the other generated from
|
* unequal. For example, with the built-in floating-point types `a == b` and `a != b` will both
|
||||||
* a default implementation. However it should
|
* evaluate to false if either `a` or `b` is NaN (cf. IEEE 754-2008 section 5.11).
|
||||||
* remain possible to implement `ne` separately, for
|
*
|
||||||
* compatibility with floating-point NaN semantics
|
* Eventually, this will be implemented by default for types that implement `TotalEq`.
|
||||||
* (cf. IEEE 754-2008 section 5.11).
|
|
||||||
*/
|
*/
|
||||||
#[lang="eq"]
|
#[lang="eq"]
|
||||||
pub trait Eq {
|
pub trait Eq {
|
||||||
@ -37,70 +35,68 @@ pub trait Eq {
|
|||||||
fn ne(&self, other: &Self) -> bool;
|
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)]
|
#[deriving(Eq)]
|
||||||
pub enum Ordering { Less, Equal, Greater }
|
pub enum Ordering { Less, Equal, Greater }
|
||||||
|
|
||||||
/// Trait for types that form a total order
|
/// Trait for types that form a total order
|
||||||
pub trait TotalOrd {
|
pub trait TotalOrd: TotalEq {
|
||||||
fn cmp(&self, other: &Self) -> Ordering;
|
fn cmp(&self, other: &Self) -> Ordering;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
macro_rules! totalord_impl(
|
||||||
fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
|
($t:ty) => {
|
||||||
if *a < *b { Less }
|
impl TotalOrd for $t {
|
||||||
else if *a > *b { Greater }
|
#[inline(always)]
|
||||||
else { Equal }
|
fn cmp(&self, other: &$t) -> Ordering {
|
||||||
}
|
if *self < *other { Less }
|
||||||
|
else if *self > *other { Greater }
|
||||||
|
else { Equal }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
impl TotalOrd for u8 {
|
totalord_impl!(u8)
|
||||||
#[inline(always)]
|
totalord_impl!(u16)
|
||||||
fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
|
totalord_impl!(u32)
|
||||||
}
|
totalord_impl!(u64)
|
||||||
|
|
||||||
impl TotalOrd for u16 {
|
totalord_impl!(i8)
|
||||||
#[inline(always)]
|
totalord_impl!(i16)
|
||||||
fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
|
totalord_impl!(i32)
|
||||||
}
|
totalord_impl!(i64)
|
||||||
|
|
||||||
impl TotalOrd for u32 {
|
totalord_impl!(int)
|
||||||
#[inline(always)]
|
totalord_impl!(uint)
|
||||||
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) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait for values that can be compared for a sort-order.
|
* 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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_int() {
|
fn test_int_totalord() {
|
||||||
assert_eq!(5.cmp(&10), Less);
|
assert_eq!(5.cmp(&10), Less);
|
||||||
assert_eq!(10.cmp(&5), Greater);
|
assert_eq!(10.cmp(&5), Greater);
|
||||||
assert_eq!(5.cmp(&5), Equal);
|
assert_eq!(5.cmp(&5), Equal);
|
||||||
assert_eq!((-5).cmp(&12), Less);
|
assert_eq!((-5).cmp(&12), Less);
|
||||||
assert_eq!(12.cmp(-5), Greater);
|
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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
@ -15,7 +15,7 @@ Functions for the unit type.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
use cmp::{Eq, Ord, TotalOrd, Ordering, Equal};
|
use prelude::*;
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
impl Eq for () {
|
impl Eq for () {
|
||||||
@ -42,3 +42,9 @@ impl TotalOrd for () {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn cmp(&self, _other: &()) -> Ordering { Equal }
|
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 */
|
/* Reexported types and traits */
|
||||||
|
|
||||||
pub use clone::Clone;
|
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 container::{Container, Mutable, Map, Set};
|
||||||
pub use hash::Hash;
|
pub use hash::Hash;
|
||||||
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
|
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
|
||||||
|
@ -21,7 +21,7 @@ use at_vec;
|
|||||||
use cast;
|
use cast;
|
||||||
use char;
|
use char;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
|
use cmp::{Equiv, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
||||||
use libc;
|
use libc;
|
||||||
use option::{None, Option, Some};
|
use option::{None, Option, Some};
|
||||||
use ptr;
|
use ptr;
|
||||||
@ -930,6 +930,30 @@ impl Eq for @str {
|
|||||||
fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
|
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)]
|
#[cfg(notest)]
|
||||||
impl Ord for ~str {
|
impl Ord for ~str {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
use container::{Container, Mutable};
|
use container::{Container, Mutable};
|
||||||
use cast;
|
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 clone::Clone;
|
||||||
use iter::BaseIter;
|
use iter::BaseIter;
|
||||||
use iter;
|
use iter;
|
||||||
@ -1547,7 +1547,7 @@ pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U {
|
|||||||
|
|
||||||
// Equality
|
// 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());
|
let (a_len, b_len) = (a.len(), b.len());
|
||||||
if a_len != b_len { return false; }
|
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; }
|
if a[i] != b[i] { return false; }
|
||||||
i += 1;
|
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
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
impl<'self,T:Eq> Eq for &'self [T] {
|
impl<'self,T:Eq> Eq for &'self [T] {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: & &'self [T]) -> bool { eq((*self), (*other)) }
|
fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ne(&self, other: & &'self [T]) -> bool { !(*self).eq(other) }
|
fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
impl<T:Eq> Eq for ~[T] {
|
impl<T:Eq> Eq for ~[T] {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &~[T]) -> bool { eq((*self), (*other)) }
|
fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ne(&self, other: &~[T]) -> bool { !(*self).eq(other) }
|
fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(notest)]
|
#[cfg(notest)]
|
||||||
impl<T:Eq> Eq for @[T] {
|
impl<T:Eq> Eq for @[T] {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &@[T]) -> bool { eq((*self), (*other)) }
|
fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) }
|
||||||
#[inline(always)]
|
#[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)]
|
#[cfg(notest)]
|
||||||
|
Loading…
Reference in New Issue
Block a user