Skip to content

Commit e549b80

Browse files
committed
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`.
2 parents d310532 + d2b267b commit e549b80

File tree

5 files changed

+134
-74
lines changed

5 files changed

+134
-74
lines changed

src/libcore/cmp.rs

+63-61
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,86 +21,82 @@ 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

40-
#[deriving(Eq)]
41-
pub enum Ordering { Less, Equal, Greater }
42-
43-
/// Trait for types that form a total order
44-
pub trait TotalOrd {
45-
fn cmp(&self, other: &Self) -> Ordering;
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;
4641
}
4742

48-
#[inline(always)]
49-
fn icmp<T: Ord>(a: &T, b: &T) -> Ordering {
50-
if *a < *b { Less }
51-
else if *a > *b { Greater }
52-
else { Equal }
53-
}
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+
)
5451

55-
impl TotalOrd for u8 {
56-
#[inline(always)]
57-
fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) }
58-
}
52+
totaleq_impl!(bool)
5953

60-
impl TotalOrd for u16 {
61-
#[inline(always)]
62-
fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) }
63-
}
54+
totaleq_impl!(u8)
55+
totaleq_impl!(u16)
56+
totaleq_impl!(u32)
57+
totaleq_impl!(u64)
6458

65-
impl TotalOrd for u32 {
66-
#[inline(always)]
67-
fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) }
68-
}
59+
totaleq_impl!(i8)
60+
totaleq_impl!(i16)
61+
totaleq_impl!(i32)
62+
totaleq_impl!(i64)
6963

70-
impl TotalOrd for u64 {
71-
#[inline(always)]
72-
fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) }
73-
}
64+
totaleq_impl!(int)
65+
totaleq_impl!(uint)
7466

75-
impl TotalOrd for i8 {
76-
#[inline(always)]
77-
fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) }
78-
}
67+
#[deriving(Eq)]
68+
pub enum Ordering { Less, Equal, Greater }
7969

80-
impl TotalOrd for i16 {
81-
#[inline(always)]
82-
fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) }
70+
/// Trait for types that form a total order
71+
pub trait TotalOrd: TotalEq {
72+
fn cmp(&self, other: &Self) -> Ordering;
8373
}
8474

85-
impl TotalOrd for i32 {
86-
#[inline(always)]
87-
fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) }
88-
}
75+
macro_rules! totalord_impl(
76+
($t:ty) => {
77+
impl TotalOrd for $t {
78+
#[inline(always)]
79+
fn cmp(&self, other: &$t) -> Ordering {
80+
if *self < *other { Less }
81+
else if *self > *other { Greater }
82+
else { Equal }
83+
}
84+
}
85+
}
86+
)
8987

90-
impl TotalOrd for i64 {
91-
#[inline(always)]
92-
fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) }
93-
}
88+
totalord_impl!(u8)
89+
totalord_impl!(u16)
90+
totalord_impl!(u32)
91+
totalord_impl!(u64)
9492

95-
impl TotalOrd for int {
96-
#[inline(always)]
97-
fn cmp(&self, other: &int) -> Ordering { icmp(self, other) }
98-
}
93+
totalord_impl!(i8)
94+
totalord_impl!(i16)
95+
totalord_impl!(i32)
96+
totalord_impl!(i64)
9997

100-
impl TotalOrd for uint {
101-
#[inline(always)]
102-
fn cmp(&self, other: &uint) -> Ordering { icmp(self, other) }
103-
}
98+
totalord_impl!(int)
99+
totalord_impl!(uint)
104100

105101
/**
106102
* 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 {
171167
#[cfg(test)]
172168
mod test {
173169
#[test]
174-
fn test_int() {
170+
fn test_int_totalord() {
175171
assert_eq!(5.cmp(&10), Less);
176172
assert_eq!(10.cmp(&5), Greater);
177173
assert_eq!(5.cmp(&5), Equal);
178174
assert_eq!((-5).cmp(&12), Less);
179175
assert_eq!(12.cmp(-5), Greater);
180176
}
177+
178+
#[test]
179+
fn test_int_totaleq() {
180+
fail_unless!(5.equals(&5));
181+
fail_unless!(!2.equals(&17));
182+
}
181183
}

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)