about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-28 02:36:49 -0700
committerbors <bors@rust-lang.org>2013-03-28 02:36:49 -0700
commite549b80e3c214f93fc6ab9d7ead3f49b585faa23 (patch)
tree2510c02dfa74370f1f5cc12b7f0592ba6fb689b5
parentd31053277aa8ced6778334d49de150b1393073eb (diff)
parentd2b267bcb5ac1adbc20bca0c170106ae3b3538ab (diff)
downloadrust-e549b80e3c214f93fc6ab9d7ead3f49b585faa23.tar.gz
rust-e549b80e3c214f93fc6ab9d7ead3f49b585faa23.zip
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`.
-rw-r--r--src/libcore/cmp.rs124
-rw-r--r--src/libcore/nil.rs10
-rw-r--r--src/libcore/prelude.rs2
-rw-r--r--src/libcore/str.rs26
-rw-r--r--src/libcore/vec.rs46
5 files changed, 134 insertions, 74 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 7c45ecae632..95f6f9bc1b5 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -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;
 }
 
-#[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.
@@ -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));
+    }
 }
diff --git a/src/libcore/nil.rs b/src/libcore/nil.rs
index 8c52ac9593a..6b8c390fc25 100644
--- a/src/libcore/nil.rs
+++ b/src/libcore/nil.rs
@@ -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 }
+}
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 7166ffbd3d3..0194e8f009c 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -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};
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 8ca65606fe2..a6f9ae84f44 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -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;
@@ -931,6 +931,30 @@ impl Eq for @str {
 }
 
 #[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)]
     fn lt(&self, other: &~str) -> bool { lt((*self), (*other)) }
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 702ae73852e..174960560df 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -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) }
+}
+
+#[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)]