Skip to content

Commit d2b267b

Browse files
committed
add a TotalEq trait
1 parent 91cb668 commit d2b267b

File tree

5 files changed

+115
-24
lines changed

5 files changed

+115
-24
lines changed

src/libcore/cmp.rs

+44-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -21,27 +21,54 @@ and `Eq` to overload the `==` and `!=` operators.
2121
*/
2222

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

38+
/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
39+
pub trait TotalEq {
40+
fn equals(&self, other: &Self) -> bool;
41+
}
42+
43+
macro_rules! totaleq_impl(
44+
($t:ty) => {
45+
impl TotalEq for $t {
46+
#[inline(always)]
47+
fn equals(&self, other: &$t) -> bool { *self == *other }
48+
}
49+
}
50+
)
51+
52+
totaleq_impl!(bool)
53+
54+
totaleq_impl!(u8)
55+
totaleq_impl!(u16)
56+
totaleq_impl!(u32)
57+
totaleq_impl!(u64)
58+
59+
totaleq_impl!(i8)
60+
totaleq_impl!(i16)
61+
totaleq_impl!(i32)
62+
totaleq_impl!(i64)
63+
64+
totaleq_impl!(int)
65+
totaleq_impl!(uint)
66+
4067
#[deriving(Eq)]
4168
pub enum Ordering { Less, Equal, Greater }
4269

4370
/// Trait for types that form a total order
44-
pub trait TotalOrd {
71+
pub trait TotalOrd: TotalEq {
4572
fn cmp(&self, other: &Self) -> Ordering;
4673
}
4774

@@ -140,11 +167,17 @@ pub fn max<T:Ord>(v1: T, v2: T) -> T {
140167
#[cfg(test)]
141168
mod test {
142169
#[test]
143-
fn test_int() {
170+
fn test_int_totalord() {
144171
assert_eq!(5.cmp(&10), Less);
145172
assert_eq!(10.cmp(&5), Greater);
146173
assert_eq!(5.cmp(&5), Equal);
147174
assert_eq!((-5).cmp(&12), Less);
148175
assert_eq!(12.cmp(-5), Greater);
149176
}
177+
178+
#[test]
179+
fn test_int_totaleq() {
180+
fail_unless!(5.equals(&5));
181+
fail_unless!(!2.equals(&17));
182+
}
150183
}

src/libcore/nil.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -15,7 +15,7 @@ Functions for the unit type.
1515
*/
1616

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

2020
#[cfg(notest)]
2121
impl Eq for () {
@@ -42,3 +42,9 @@ impl TotalOrd for () {
4242
#[inline(always)]
4343
fn cmp(&self, _other: &()) -> Ordering { Equal }
4444
}
45+
46+
#[cfg(notest)]
47+
impl TotalEq for () {
48+
#[inline(always)]
49+
fn equals(&self, _other: &()) -> bool { true }
50+
}

src/libcore/prelude.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub use result::{Result, Ok, Err};
2424
/* Reexported types and traits */
2525

2626
pub use clone::Clone;
27-
pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
27+
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
2828
pub use container::{Container, Mutable, Map, Set};
2929
pub use hash::Hash;
3030
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};

src/libcore/str.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use at_vec;
2121
use cast;
2222
use char;
2323
use clone::Clone;
24-
use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
24+
use cmp::{Equiv, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
2525
use libc;
2626
use option::{None, Option, Some};
2727
use ptr;
@@ -930,6 +930,30 @@ impl Eq for @str {
930930
fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
931931
}
932932
933+
#[cfg(notest)]
934+
impl<'self> TotalEq for &'self str {
935+
#[inline(always)]
936+
fn equals(&self, other: & &'self str) -> bool {
937+
eq_slice((*self), (*other))
938+
}
939+
}
940+
941+
#[cfg(notest)]
942+
impl TotalEq for ~str {
943+
#[inline(always)]
944+
fn equals(&self, other: &~str) -> bool {
945+
eq_slice((*self), (*other))
946+
}
947+
}
948+
949+
#[cfg(notest)]
950+
impl TotalEq for @str {
951+
#[inline(always)]
952+
fn equals(&self, other: &@str) -> bool {
953+
eq_slice((*self), (*other))
954+
}
955+
}
956+
933957
#[cfg(notest)]
934958
impl Ord for ~str {
935959
#[inline(always)]

src/libcore/vec.rs

+37-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

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

15481548
// Equality
15491549

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

@@ -1556,33 +1556,61 @@ fn eq<T:Eq>(a: &[T], b: &[T]) -> bool {
15561556
if a[i] != b[i] { return false; }
15571557
i += 1;
15581558
}
1559+
true
1560+
}
1561+
1562+
fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool {
1563+
let (a_len, b_len) = (a.len(), b.len());
1564+
if a_len != b_len { return false; }
15591565

1566+
let mut i = 0;
1567+
while i < a_len {
1568+
if !a[i].equals(&b[i]) { return false; }
1569+
i += 1;
1570+
}
15601571
true
15611572
}
15621573

15631574
#[cfg(notest)]
15641575
impl<'self,T:Eq> Eq for &'self [T] {
15651576
#[inline(always)]
1566-
fn eq(&self, other: & &'self [T]) -> bool { eq((*self), (*other)) }
1577+
fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) }
15671578
#[inline(always)]
1568-
fn ne(&self, other: & &'self [T]) -> bool { !(*self).eq(other) }
1579+
fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) }
15691580
}
15701581

1571-
15721582
#[cfg(notest)]
15731583
impl<T:Eq> Eq for ~[T] {
15741584
#[inline(always)]
1575-
fn eq(&self, other: &~[T]) -> bool { eq((*self), (*other)) }
1585+
fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) }
15761586
#[inline(always)]
1577-
fn ne(&self, other: &~[T]) -> bool { !(*self).eq(other) }
1587+
fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
15781588
}
15791589

15801590
#[cfg(notest)]
15811591
impl<T:Eq> Eq for @[T] {
15821592
#[inline(always)]
1583-
fn eq(&self, other: &@[T]) -> bool { eq((*self), (*other)) }
1593+
fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) }
1594+
#[inline(always)]
1595+
fn ne(&self, other: &@[T]) -> bool { !self.eq(other) }
1596+
}
1597+
1598+
#[cfg(notest)]
1599+
impl<'self,T:TotalEq> TotalEq for &'self [T] {
1600+
#[inline(always)]
1601+
fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) }
1602+
}
1603+
1604+
#[cfg(notest)]
1605+
impl<T:TotalEq> TotalEq for ~[T] {
1606+
#[inline(always)]
1607+
fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) }
1608+
}
1609+
1610+
#[cfg(notest)]
1611+
impl<T:TotalEq> TotalEq for @[T] {
15841612
#[inline(always)]
1585-
fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) }
1613+
fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) }
15861614
}
15871615

15881616
#[cfg(notest)]

0 commit comments

Comments
 (0)