auto merge of #18467 : japaric/rust/eq, r=alexcrichton

`eq`, `ne`, `cmp`, etc methods now require one less level of indirection when dealing with `&str`/`&[T]`

``` rust
"foo".ne(&"bar") -> "foo".ne("bar")
slice.cmp(&another_slice) -> slice.cmp(another_slice)
// slice and another_slice have type `&[T]`
```

[breaking-change]
This commit is contained in:
bors 2014-11-06 08:06:50 +00:00
commit e84e7a00dd
22 changed files with 635 additions and 29 deletions

View File

@ -61,12 +61,16 @@ impl<T: Clone> Clone for Box<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T:PartialEq> PartialEq for Box<T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
#[inline]
fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T:PartialOrd> PartialOrd for Box<T> {
#[inline]
fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
@ -81,14 +85,50 @@ impl<T:PartialOrd> PartialOrd for Box<T> {
#[inline]
fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord> Ord for Box<T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> Ordering {
(**self).cmp(&**other)
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T: Eq> Eq for Box<T> {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<Sized? T: PartialEq> PartialEq for Box<T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
#[inline]
fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
#[inline]
fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
#[inline]
fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
#[inline]
fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
#[inline]
fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<Sized? T: Ord> Ord for Box<T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<Sized? T: Eq> Eq for Box<T> {}
/// Extension methods for an owning `Any` trait object.
#[unstable = "post-DST and coherence changes, this will not be a trait but \
rather a direct `impl` on `Box<Any>`"]

View File

@ -1598,15 +1598,15 @@ mod tests {
#[test]
fn test_total_ord() {
let c: &[int] = &[1, 2, 3];
[1, 2, 3, 4][].cmp(& c) == Greater;
[1, 2, 3, 4][].cmp(c) == Greater;
let c: &[int] = &[1, 2, 3, 4];
[1, 2, 3][].cmp(& c) == Less;
[1, 2, 3][].cmp(c) == Less;
let c: &[int] = &[1, 2, 3, 6];
[1, 2, 3, 4][].cmp(& c) == Equal;
[1, 2, 3, 4][].cmp(c) == Equal;
let c: &[int] = &[1, 2, 3, 4, 5, 6];
[1, 2, 3, 4, 5, 5, 5, 5][].cmp(& c) == Less;
[1, 2, 3, 4, 5, 5, 5, 5][].cmp(c) == Less;
let c: &[int] = &[1, 2, 3, 4];
[2, 2][].cmp(& c) == Greater;
[2, 2][].cmp(c) == Greater;
}
#[test]

View File

@ -532,10 +532,17 @@ impl<'a> PartialOrd for MaybeOwned<'a> {
}
impl<'a> Ord for MaybeOwned<'a> {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
#[inline]
fn cmp(&self, other: &MaybeOwned) -> Ordering {
self.as_slice().cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[inline]
fn cmp(&self, other: &MaybeOwned) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
@ -1523,11 +1530,11 @@ mod tests {
#[test]
fn test_total_ord() {
"1234".cmp(&("123")) == Greater;
"123".cmp(&("1234")) == Less;
"1234".cmp(&("1234")) == Equal;
"12345555".cmp(&("123456")) == Less;
"22".cmp(&("1234")) == Greater;
"1234".cmp("123") == Greater;
"123".cmp("1234") == Less;
"1234".cmp("1234") == Equal;
"12345555".cmp("123456") == Less;
"22".cmp("1234") == Greater;
}
#[test]

View File

@ -579,7 +579,7 @@ impl<K, V> TreeMap<K, V> {
/// let headers = get_headers();
/// let ua_key = "User-Agent";
/// let ua = headers.find_with(|k| {
/// ua_key.cmp(&k.as_slice())
/// ua_key.cmp(k.as_slice())
/// });
///
/// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1");
@ -603,7 +603,7 @@ impl<K, V> TreeMap<K, V> {
/// t.insert("User-Agent", "Curl-Rust/0.1");
///
/// let new_ua = "Safari/156.0";
/// match t.find_with_mut(|k| "User-Agent".cmp(k)) {
/// match t.find_with_mut(|&k| "User-Agent".cmp(k)) {
/// Some(x) => *x = new_ua,
/// None => panic!(),
/// }
@ -1302,7 +1302,7 @@ mod test_treemap {
#[test]
fn find_with_empty() {
let m: TreeMap<&'static str,int> = TreeMap::new();
assert!(m.find_with(|k| "test".cmp(k)) == None);
assert!(m.find_with(|&k| "test".cmp(k)) == None);
}
#[test]
@ -1311,7 +1311,7 @@ mod test_treemap {
assert!(m.insert("test1", 2i));
assert!(m.insert("test2", 3i));
assert!(m.insert("test3", 3i));
assert_eq!(m.find_with(|k| "test4".cmp(k)), None);
assert_eq!(m.find_with(|&k| "test4".cmp(k)), None);
}
#[test]
@ -1320,7 +1320,7 @@ mod test_treemap {
assert!(m.insert("test1", 2i));
assert!(m.insert("test2", 3i));
assert!(m.insert("test3", 4i));
assert_eq!(m.find_with(|k| "test2".cmp(k)), Some(&3i));
assert_eq!(m.find_with(|&k| "test2".cmp(k)), Some(&3i));
}
#[test]
@ -1343,10 +1343,10 @@ mod test_treemap {
assert!(m.insert("t2", 8));
assert!(m.insert("t5", 14));
let new = 100;
match m.find_with_mut(|k| "t5".cmp(k)) {
match m.find_with_mut(|&k| "t5".cmp(k)) {
None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find_with(|k| "t5".cmp(k)), Some(&new));
assert_eq!(m.find_with(|&k| "t5".cmp(k)), Some(&new));
}
#[test]

View File

@ -506,10 +506,17 @@ impl<T: PartialEq> PartialEq for Vec<T> {
#[unstable = "waiting on PartialOrd stability"]
impl<T: PartialOrd> PartialOrd for Vec<T> {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
#[inline]
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
self.as_slice().partial_cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[inline]
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
#[unstable = "waiting on Eq stability"]
@ -523,10 +530,17 @@ impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for Vec<T> {
#[unstable = "waiting on Ord stability"]
impl<T: Ord> Ord for Vec<T> {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
#[inline]
fn cmp(&self, other: &Vec<T>) -> Ordering {
self.as_slice().cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[inline]
fn cmp(&self, other: &Vec<T>) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
// FIXME: #13996: need a way to mark the return value as `noalias`

View File

@ -55,6 +55,8 @@ use option::{Option, Some, None};
///
/// Eventually, this will be implemented by default for types that implement
/// `Eq`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[lang="eq"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialEq {
@ -66,6 +68,31 @@ pub trait PartialEq {
fn ne(&self, other: &Self) -> bool { !self.eq(other) }
}
/// Trait for values that can be compared for equality and inequality.
///
/// This trait allows for partial equality, for types that do not have an
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not `Eq`.
///
/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
/// in terms of it by default. Any manual implementation of `ne` *must* respect
/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
/// only if `a != b`.
///
/// Eventually, this will be implemented by default for types that implement
/// `Eq`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[lang="eq"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialEq for Sized? {
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
fn eq(&self, other: &Self) -> bool;
/// This method tests for `!=`.
#[inline]
fn ne(&self, other: &Self) -> bool { !self.eq(other) }
}
/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
@ -75,6 +102,8 @@ pub trait PartialEq {
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[unstable = "Definition may change slightly after trait reform"]
pub trait Eq: PartialEq {
// FIXME #13101: this method is used solely by #[deriving] to
@ -89,6 +118,30 @@ pub trait Eq: PartialEq {
fn assert_receiver_is_total_eq(&self) {}
}
/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
/// This means, that in addition to `a == b` and `a != b` being strict
/// inverses, the equality must be (for all `a`, `b` and `c`):
///
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Definition may change slightly after trait reform"]
pub trait Eq for Sized?: PartialEq {
// FIXME #13101: this method is used solely by #[deriving] to
// assert that every component of a type implements #[deriving]
// itself, the current deriving infrastructure means doing this
// assertion without using a method on this trait is nearly
// impossible.
//
// This should never be implemented by hand.
#[doc(hidden)]
#[inline(always)]
fn assert_receiver_is_total_eq(&self) {}
}
/// An ordering is, e.g, a result of a comparison between two values.
#[deriving(Clone, PartialEq, Show)]
#[stable]
@ -145,6 +198,8 @@ impl Ordering {
/// true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[unstable = "Definition may change slightly after trait reform"]
pub trait Ord: Eq + PartialOrd {
/// This method returns an ordering between `self` and `other` values.
@ -160,6 +215,31 @@ pub trait Ord: Eq + PartialOrd {
fn cmp(&self, other: &Self) -> Ordering;
}
/// Trait for types that form a [total order](
/// https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
///
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is
/// true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Definition may change slightly after trait reform"]
pub trait Ord for Sized?: Eq + PartialOrd {
/// This method returns an ordering between `self` and `other` values.
///
/// By convention, `self.cmp(&other)` returns the ordering matching
/// the expression `self <operator> other` if true. For example:
///
/// ```
/// assert_eq!( 5u.cmp(&10), Less); // because 5 < 10
/// assert_eq!(10u.cmp(&5), Greater); // because 10 > 5
/// assert_eq!( 5u.cmp(&5), Equal); // because 5 == 5
/// ```
fn cmp(&self, other: &Self) -> Ordering;
}
#[unstable = "Trait is unstable."]
impl Eq for Ordering {}
@ -188,6 +268,8 @@ impl PartialOrd for Ordering {
/// which do not have a total order. For example, for floating point numbers,
/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
/// 5.11).
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
#[lang="ord"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialOrd: PartialEq {
@ -232,6 +314,60 @@ pub trait PartialOrd: PartialEq {
}
}
/// Trait for values that can be compared for a sort-order.
///
/// PartialOrd only requires implementation of the `partial_cmp` method,
/// with the others generated from default implementations.
///
/// However it remains possible to implement the others separately for types
/// which do not have a total order. For example, for floating point numbers,
/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
/// 5.11).
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[lang="ord"]
#[unstable = "Definition may change slightly after trait reform"]
pub trait PartialOrd for Sized?: PartialEq {
/// This method returns an ordering between `self` and `other` values
/// if one exists.
fn partial_cmp(&self, other: &Self) -> Option<Ordering>;
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
#[inline]
fn lt(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Less) => true,
_ => false,
}
}
/// This method tests less than or equal to (`<=`).
#[inline]
fn le(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Less) | Some(Equal) => true,
_ => false,
}
}
/// This method tests greater than (`>`).
#[inline]
fn gt(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Greater) => true,
_ => false,
}
}
/// This method tests greater than or equal to (`>=`).
#[inline]
fn ge(&self, other: &Self) -> bool {
match self.partial_cmp(other) {
Some(Greater) | Some(Equal) => true,
_ => false,
}
}
}
/// The equivalence relation. Two values may be equivalent even if they are
/// of different types. The most common use case for this relation is
/// container types; e.g. it is often desirable to be able to use `&str`
@ -286,6 +422,8 @@ pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
mod impls {
use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering,
Less, Greater, Equal};
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
use kinds::Sized;
use option::{Option, Some, None};
macro_rules! partial_eq_impl(
@ -393,6 +531,8 @@ mod impls {
ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
// & pointers
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialEq> PartialEq for &'a T {
#[inline]
@ -400,6 +540,8 @@ mod impls {
#[inline]
fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialOrd> PartialOrd for &'a T {
#[inline]
@ -415,15 +557,55 @@ mod impls {
#[inline]
fn gt(&self, other: & &'a T) -> bool { *(*self) > *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Ord> Ord for &'a T {
#[inline]
fn cmp(&self, other: & &'a T) -> Ordering { (**self).cmp(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Eq> Eq for &'a T {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialEq> PartialEq for &'a T {
#[inline]
fn eq(&self, other: & &'a T) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: & &'a T) -> bool { PartialEq::ne(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialOrd> PartialOrd for &'a T {
#[inline]
fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: & &'a T) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
fn le(&self, other: & &'a T) -> bool { PartialOrd::le(*self, *other) }
#[inline]
fn ge(&self, other: & &'a T) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
fn gt(&self, other: & &'a T) -> bool { PartialOrd::gt(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Ord> Ord for &'a T {
#[inline]
fn cmp(&self, other: & &'a T) -> Ordering { Ord::cmp(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Eq> Eq for &'a T {}
// &mut pointers
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialEq> PartialEq for &'a mut T {
#[inline]
@ -431,6 +613,8 @@ mod impls {
#[inline]
fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: PartialOrd> PartialOrd for &'a mut T {
#[inline]
@ -446,11 +630,49 @@ mod impls {
#[inline]
fn gt(&self, other: &&'a mut T) -> bool { **self > **other }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Ord> Ord for &'a mut T {
#[inline]
fn cmp(&self, other: &&'a mut T) -> Ordering { (**self).cmp(*other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "Trait is unstable."]
impl<'a, T: Eq> Eq for &'a mut T {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialEq> PartialEq for &'a mut T {
#[inline]
fn eq(&self, other: &&'a mut T) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: &&'a mut T) -> bool { PartialEq::ne(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: PartialOrd> PartialOrd for &'a mut T {
#[inline]
fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&'a mut T) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
fn le(&self, other: &&'a mut T) -> bool { PartialOrd::le(*self, *other) }
#[inline]
fn ge(&self, other: &&'a mut T) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
fn gt(&self, other: &&'a mut T) -> bool { PartialOrd::gt(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Ord> Ord for &'a mut T {
#[inline]
fn cmp(&self, other: &&'a mut T) -> Ordering { Ord::cmp(*self, *other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "Trait is unstable."]
impl<'a, Sized? T: Eq> Eq for &'a mut T {}
}

View File

@ -143,7 +143,7 @@
#![stable]
use cmp::{PartialEq, Eq, Ord};
use cmp::{Eq, Ord};
use default::Default;
use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize};
use mem;

View File

@ -276,7 +276,6 @@
#![stable]
use cmp::PartialEq;
use std::fmt::Show;
use slice;
use slice::AsSlice;

View File

@ -1555,6 +1555,8 @@ pub mod bytes {
// Boilerplate traits
//
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:PartialEq> PartialEq for &'a [T] {
fn eq(&self, other: & &'a [T]) -> bool {
@ -1567,15 +1569,36 @@ impl<'a,T:PartialEq> PartialEq for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: PartialEq> PartialEq for [T] {
fn eq(&self, other: &[T]) -> bool {
self.len() == other.len() &&
order::eq(self.iter(), other.iter())
}
fn ne(&self, other: &[T]) -> bool {
self.len() != other.len() ||
order::ne(self.iter(), other.iter())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Eq> Eq for &'a [T] {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: Eq> Eq for [T] {}
#[unstable = "waiting for DST"]
impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for [T] {
#[inline]
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:PartialEq> PartialEq for &'a mut [T] {
fn eq(&self, other: & &'a mut [T]) -> bool {
@ -1588,6 +1611,8 @@ impl<'a,T:PartialEq> PartialEq for &'a mut [T] {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Eq> Eq for &'a mut [T] {}
@ -1597,6 +1622,8 @@ impl<'a,T:PartialEq, V: AsSlice<T>> Equiv<V> for &'a mut [T] {
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a,T:Ord> Ord for &'a [T] {
fn cmp(&self, other: & &'a [T]) -> Ordering {
@ -1604,6 +1631,16 @@ impl<'a,T:Ord> Ord for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: Ord> Ord for [T] {
fn cmp(&self, other: &[T]) -> Ordering {
order::cmp(self.iter(), other.iter())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
#[unstable = "waiting for DST"]
impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
#[inline]
@ -1628,6 +1665,31 @@ impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[unstable = "waiting for DST"]
impl<T: PartialOrd> PartialOrd for [T] {
#[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
order::partial_cmp(self.iter(), other.iter())
}
#[inline]
fn lt(&self, other: &[T]) -> bool {
order::lt(self.iter(), other.iter())
}
#[inline]
fn le(&self, other: &[T]) -> bool {
order::le(self.iter(), other.iter())
}
#[inline]
fn ge(&self, other: &[T]) -> bool {
order::ge(self.iter(), other.iter())
}
#[inline]
fn gt(&self, other: &[T]) -> bool {
order::gt(self.iter(), other.iter())
}
}
/// Extension methods for immutable slices containing integers.
#[experimental]
pub trait ImmutableIntSlice<U, S> for Sized? {

View File

@ -19,8 +19,7 @@
use mem;
use char;
use char::Char;
use cmp;
use cmp::{PartialEq, Eq};
use cmp::{Eq, mod};
use default::Default;
use iter::{Map, Iterator};
use iter::{DoubleEndedIterator, ExactSize};
@ -1123,6 +1122,8 @@ pub mod traits {
use ops;
use str::{Str, StrSlice, eq_slice};
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> Ord for &'a str {
#[inline]
fn cmp(&self, other: & &'a str) -> Ordering {
@ -1138,6 +1139,24 @@ pub mod traits {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl Ord for str {
#[inline]
fn cmp(&self, other: &str) -> Ordering {
for (s_b, o_b) in self.bytes().zip(other.bytes()) {
match s_b.cmp(&o_b) {
Greater => return Greater,
Less => return Less,
Equal => ()
}
}
self.len().cmp(&other.len())
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> PartialEq for &'a str {
#[inline]
fn eq(&self, other: & &'a str) -> bool {
@ -1147,8 +1166,25 @@ pub mod traits {
fn ne(&self, other: & &'a str) -> bool { !(*self).eq(other) }
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl PartialEq for str {
#[inline]
fn eq(&self, other: &str) -> bool {
eq_slice(self, other)
}
#[inline]
fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> Eq for &'a str {}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl Eq for str {}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> PartialOrd for &'a str {
#[inline]
fn partial_cmp(&self, other: &&'a str) -> Option<Ordering> {
@ -1156,6 +1192,14 @@ pub mod traits {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl PartialOrd for str {
#[inline]
fn partial_cmp(&self, other: &str) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<S: Str> Equiv<S> for str {
#[inline]
fn equiv(&self, other: &S) -> bool { eq_slice(self, other.as_slice()) }

View File

@ -93,7 +93,6 @@
#[cfg(test)] #[phase(plugin, link)] extern crate log;
use std::cmp::PartialEq;
use std::fmt;
use std::result::{Err, Ok};
use std::result;

View File

@ -76,15 +76,27 @@ impl<'a, T: PartialEq> PartialEq for MaybeOwnedVector<'a, T> {
impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {}
impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
fn partial_cmp(&self, other: &MaybeOwnedVector<T>) -> Option<Ordering> {
self.as_slice().partial_cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn partial_cmp(&self, other: &MaybeOwnedVector<T>) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
self.as_slice().cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<'a, T: PartialEq, V: AsSlice<T>> Equiv<V> for MaybeOwnedVector<'a, T> {

View File

@ -1020,6 +1020,8 @@ fn is_valid_cap(c: char) -> bool {
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
match classes.binary_search(|&(s, _)| s.cmp(&name)) {
slice::Found(i) => Some(classes[i].val1().to_vec()),
@ -1027,6 +1029,14 @@ fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
match classes.binary_search(|&(s, _)| s.cmp(name)) {
slice::Found(i) => Some(classes[i].val1().to_vec()),
slice::NotFound(_) => None,
}
}
type Class = &'static [(char, char)];
type NamedClasses = &'static [(&'static str, &'static Class)];

View File

@ -182,6 +182,8 @@ Available lint options:
");
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
lints.sort_by(|x: &&Lint, y: &&Lint| {
@ -194,6 +196,21 @@ Available lint options:
lints
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
lints.sort_by(|x: &&Lint, y: &&Lint| {
match x.default_level.cmp(&y.default_level) {
// The sort doesn't case-fold but it's doubtful we care.
Equal => x.name.cmp(y.name),
r => r,
}
});
lints
}
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
-> Vec<(&'static str, Vec<lint::LintId>)> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
@ -204,6 +221,17 @@ Available lint options:
lints
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
-> Vec<(&'static str, Vec<lint::LintId>)> {
let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
lints.sort_by(|&(x, _): &(&'static str, Vec<lint::LintId>),
&(y, _): &(&'static str, Vec<lint::LintId>)| {
x.cmp(y)
});
lints
}
let (plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
let plugin = sort_lints(plugin);
let builtin = sort_lints(builtin);

View File

@ -121,10 +121,17 @@ impl PartialEq for CString {
}
impl PartialOrd for CString {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
#[inline]
fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
self.as_bytes().partial_cmp(&other.as_bytes())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[inline]
fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
self.as_bytes().partial_cmp(other.as_bytes())
}
}
impl Eq for CString {}

View File

@ -890,6 +890,8 @@ impl Json {
/// If the Json value is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
match self {
&Object(ref map) => map.find_with(|s| key.cmp(&s.as_slice())),
@ -897,6 +899,16 @@ impl Json {
}
}
/// If the Json value is an Object, returns the value associated with the provided key.
/// Otherwise, returns None.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
match self {
&Object(ref map) => map.find_with(|s| key.cmp(s.as_slice())),
_ => None
}
}
/// Attempts to get a nested Json Object for each key in `keys`.
/// If any key is found not to exist, find_path will return None.
/// Otherwise, it will return the Json value associated with the final key.
@ -914,6 +926,8 @@ impl Json {
/// If the Json value is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the Json value is not an Object, returns None.
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
match self {
&Object(ref map) => {
@ -934,6 +948,30 @@ impl Json {
}
}
/// If the Json value is an Object, performs a depth-first search until
/// a value associated with the provided key is found. If no value is found
/// or the Json value is not an Object, returns None.
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
match self {
&Object(ref map) => {
match map.find_with(|s| key.cmp(s.as_slice())) {
Some(json_value) => Some(json_value),
None => {
for (_, v) in map.iter() {
match v.search(key) {
x if x.is_some() => return x,
_ => ()
}
}
None
}
}
},
_ => None
}
}
/// Returns true if the Json value is an Object. Returns false otherwise.
pub fn is_object<'a>(&'a self) -> bool {
self.as_object().is_some()

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{MetaItem, Item, Expr};
use ast::{MetaItem, Item, Expr, mod};
use codemap::Span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
@ -25,12 +25,38 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
// structures are equal if all fields are equal, and non equal, if
// any fields are not equal or if the enum variants are different
fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
cs_and(|cx, span, _, _| cx.expr_bool(span, false),
cx, span, substr)
cs_fold(
true, // use foldl
|cx, span, subexpr, self_f, other_fs| {
let other_f = match other_fs {
[ref o_f] => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Eq)`")
};
let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone());
cx.expr_binary(span, ast::BiAnd, subexpr, eq)
},
cx.expr_bool(span, true),
|cx, span, _, _| cx.expr_bool(span, false),
cx, span, substr)
}
fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
cs_or(|cx, span, _, _| cx.expr_bool(span, true),
cx, span, substr)
cs_fold(
true, // use foldl
|cx, span, subexpr, self_f, other_fs| {
let other_f = match other_fs {
[ref o_f] => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Eq)`")
};
let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone());
cx.expr_binary(span, ast::BiOr, subexpr, eq)
},
cx.expr_bool(span, false),
|cx, span, _, _| cx.expr_bool(span, true),
cx, span, substr)
}
macro_rules! md (

View File

@ -97,9 +97,15 @@ pub struct RcStr {
impl Eq for RcStr {}
impl Ord for RcStr {
// NOTE(stage0): remove method after a snapshot
#[cfg(stage0)]
fn cmp(&self, other: &RcStr) -> Ordering {
self.as_slice().cmp(&other.as_slice())
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
fn cmp(&self, other: &RcStr) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl Str for RcStr {

View File

@ -973,6 +973,8 @@ fn get_concurrency() -> uint {
}
}
// NOTE(stage0): remove function after a snapshot
#[cfg(stage0)]
pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
let mut filtered = tests;
@ -1020,6 +1022,54 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
let mut filtered = tests;
// Remove tests that don't match the test filter
filtered = match opts.filter {
None => filtered,
Some(ref re) => {
filtered.into_iter()
.filter(|test| re.is_match(test.desc.name.as_slice())).collect()
}
};
// Maybe pull out the ignored test and unignore them
filtered = if !opts.run_ignored {
filtered
} else {
fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
if test.desc.ignore {
let TestDescAndFn {desc, testfn} = test;
Some(TestDescAndFn {
desc: TestDesc {ignore: false, ..desc},
testfn: testfn
})
} else {
None
}
};
filtered.into_iter().filter_map(|x| filter(x)).collect()
};
// Sort the tests alphabetically
filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
// Shard the remaining tests, if sharding requested.
match opts.test_shard {
None => filtered,
Some((a,b)) => {
filtered.into_iter().enumerate()
// note: using a - 1 so that the valid shards, for example, are
// 1.2 and 2.2 instead of 0.2 and 1.2
.filter(|&(i,_)| i % b == (a - 1))
.map(|(_,t)| t)
.collect()
}
}
}
pub fn run_test(opts: &TestOpts,
force_ignore: bool,
test: TestDescAndFn,

View File

@ -12,8 +12,8 @@ struct NoCloneOrEq;
#[deriving(PartialEq)]
struct E {
x: NoCloneOrEq //~ ERROR does not implement any method in scope named `eq`
//~^ ERROR does not implement any method in scope named `ne`
x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq`
//~^ ERROR binary operation `!=` cannot be applied to type `NoCloneOrEq`
}
#[deriving(Clone)]
struct C {

View File

@ -0,0 +1,24 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(PartialEq, PartialOrd, Eq, Ord)]
struct Foo(Box<[u8]>);
pub fn main() {
let a = Foo(box [0, 1, 2]);
let b = Foo(box [0, 1, 2]);
assert!(a == b);
println!("{}", a != b);
println!("{}", a < b);
println!("{}", a <= b);
println!("{}", a == b);
println!("{}", a > b);
println!("{}", a >= b);
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(PartialEq)]
enum Test<'a> {
Slice(&'a int)
}
fn main() {
assert!(Slice(&1) == Slice(&1))
}