Skip to content

implement a TotalEq trait #5587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 63 additions & 61 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand All @@ -21,86 +21,82 @@ 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 {
fn eq(&self, other: &Self) -> bool;
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.
Expand Down Expand Up @@ -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));
}
}
10 changes: 8 additions & 2 deletions src/libcore/nil.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand All @@ -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 () {
Expand All @@ -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 }
}
2 changes: 1 addition & 1 deletion src/libcore/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
26 changes: 25 additions & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)]
Expand Down
46 changes: 37 additions & 9 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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; }

Expand All @@ -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)]
Expand Down