Skip to content

Commit 6d965cc

Browse files
committed
auto merge of #19167 : japaric/rust/rhs-cmp, r=aturon
Comparison traits have gained an `Rhs` input parameter that defaults to `Self`. And now the comparison operators can be overloaded to work between different types. In particular, this PR allows the following operations (and their commutative versions): - `&str` == `String` == `CowString` - `&[A]` == `&mut [B]` == `Vec<C>` == `CowVec<D>` == `[E, ..N]` (for `N` up to 32) - `&mut A` == `&B` (for `Sized` `A` and `B`) Where `A`, `B`, `C`, `D`, `E` may be different types that implement `PartialEq`. For example, these comparisons are now valid: `string == "foo"`, and `vec_of_strings == ["Hello", "world"]`. [breaking-change]s Since the `==` may now work on different types, operations that relied on the old "same type restriction" to drive type inference, will need to be type annotated. These are the most common fallout cases: - `some_vec == some_iter.collect()`: `collect` needs to be type annotated: `collect::<Vec<_>>()` - `slice == &[a, b, c]`: RHS doesn't get coerced to an slice, use an array instead `[a, b, c]` - `lhs == []`: Change expression to `lhs.is_empty()` - `lhs == some_generic_function()`: Type annotate the RHS as necessary cc #19148 r? @aturon
2 parents 53e8bd6 + 5cfac94 commit 6d965cc

File tree

41 files changed

+421
-222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+421
-222
lines changed

src/libcollections/dlist.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -945,15 +945,15 @@ mod tests {
945945
let mut m = list_from(v.as_slice());
946946
m.rotate_backward(); check_links(&m);
947947
m.rotate_forward(); check_links(&m);
948-
assert_eq!(v.iter().collect::<Vec<&int>>(), m.iter().collect());
948+
assert_eq!(v.iter().collect::<Vec<&int>>(), m.iter().collect::<Vec<_>>());
949949
m.rotate_forward(); check_links(&m);
950950
m.rotate_forward(); check_links(&m);
951951
m.pop_front(); check_links(&m);
952952
m.rotate_forward(); check_links(&m);
953953
m.rotate_backward(); check_links(&m);
954954
m.push_front(9); check_links(&m);
955955
m.rotate_forward(); check_links(&m);
956-
assert_eq!(vec![3i,9,5,1,2], m.into_iter().collect());
956+
assert_eq!(vec![3i,9,5,1,2], m.into_iter().collect::<Vec<_>>());
957957
}
958958

959959
#[test]

src/libcollections/enum_set.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -397,23 +397,23 @@ mod test {
397397
fn test_iterator() {
398398
let mut e1: EnumSet<Foo> = EnumSet::new();
399399

400-
let elems: Vec<Foo> = e1.iter().collect();
400+
let elems: ::vec::Vec<Foo> = e1.iter().collect();
401401
assert!(elems.is_empty())
402402

403403
e1.insert(A);
404-
let elems = e1.iter().collect();
404+
let elems: ::vec::Vec<_> = e1.iter().collect();
405405
assert_eq!(vec![A], elems)
406406

407407
e1.insert(C);
408-
let elems = e1.iter().collect();
408+
let elems: ::vec::Vec<_> = e1.iter().collect();
409409
assert_eq!(vec![A,C], elems)
410410

411411
e1.insert(C);
412-
let elems = e1.iter().collect();
412+
let elems: ::vec::Vec<_> = e1.iter().collect();
413413
assert_eq!(vec![A,C], elems)
414414

415415
e1.insert(B);
416-
let elems = e1.iter().collect();
416+
let elems: ::vec::Vec<_> = e1.iter().collect();
417417
assert_eq!(vec![A,B,C], elems)
418418
}
419419

@@ -431,35 +431,35 @@ mod test {
431431
e2.insert(C);
432432

433433
let e_union = e1 | e2;
434-
let elems = e_union.iter().collect();
434+
let elems: ::vec::Vec<_> = e_union.iter().collect();
435435
assert_eq!(vec![A,B,C], elems)
436436

437437
let e_intersection = e1 & e2;
438-
let elems = e_intersection.iter().collect();
438+
let elems: ::vec::Vec<_> = e_intersection.iter().collect();
439439
assert_eq!(vec![C], elems)
440440

441441
// Another way to express intersection
442442
let e_intersection = e1 - (e1 - e2);
443-
let elems = e_intersection.iter().collect();
443+
let elems: ::vec::Vec<_> = e_intersection.iter().collect();
444444
assert_eq!(vec![C], elems)
445445

446446
let e_subtract = e1 - e2;
447-
let elems = e_subtract.iter().collect();
447+
let elems: ::vec::Vec<_> = e_subtract.iter().collect();
448448
assert_eq!(vec![A], elems)
449449

450450
// Bitwise XOR of two sets, aka symmetric difference
451451
let e_symmetric_diff = e1 ^ e2;
452-
let elems = e_symmetric_diff.iter().collect();
452+
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
453453
assert_eq!(vec![A,B], elems)
454454

455455
// Another way to express symmetric difference
456456
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
457-
let elems = e_symmetric_diff.iter().collect();
457+
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
458458
assert_eq!(vec![A,B], elems)
459459

460460
// Yet another way to express symmetric difference
461461
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
462-
let elems = e_symmetric_diff.iter().collect();
462+
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
463463
assert_eq!(vec![A,B], elems)
464464
}
465465

src/libcollections/str.rs

+1
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ impl<'a> Ord for MaybeOwned<'a> {
563563
}
564564
}
565565

566+
#[allow(deprecated)]
566567
#[deprecated = "use std::str::CowString"]
567568
impl<'a, S: Str> Equiv<S> for MaybeOwned<'a> {
568569
#[inline]

src/libcollections/string.rs

+50-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use str::{CharRange, CowString, FromStr, StrAllocating, Owned};
3030
use vec::{DerefVec, Vec, as_vec};
3131

3232
/// A growable string stored as a UTF-8 encoded buffer.
33-
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
33+
#[deriving(Clone, PartialOrd, Eq, Ord)]
3434
#[stable]
3535
pub struct String {
3636
vec: Vec<u8>,
@@ -738,6 +738,49 @@ impl Extend<char> for String {
738738
}
739739
}
740740

741+
impl PartialEq for String {
742+
#[inline]
743+
fn eq(&self, other: &String) -> bool { PartialEq::eq(&**self, &**other) }
744+
#[inline]
745+
fn ne(&self, other: &String) -> bool { PartialEq::ne(&**self, &**other) }
746+
}
747+
748+
macro_rules! impl_eq {
749+
($lhs:ty, $rhs: ty) => {
750+
impl<'a> PartialEq<$rhs> for $lhs {
751+
#[inline]
752+
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
753+
#[inline]
754+
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
755+
}
756+
757+
impl<'a> PartialEq<$lhs> for $rhs {
758+
#[inline]
759+
fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
760+
#[inline]
761+
fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) }
762+
}
763+
764+
}
765+
}
766+
767+
impl_eq!(String, &'a str)
768+
impl_eq!(CowString<'a>, String)
769+
770+
impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
771+
#[inline]
772+
fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
773+
#[inline]
774+
fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&**self, &**other) }
775+
}
776+
777+
impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
778+
#[inline]
779+
fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) }
780+
#[inline]
781+
fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) }
782+
}
783+
741784
#[experimental = "waiting on Str stabilization"]
742785
impl Str for String {
743786
#[inline]
@@ -779,7 +822,8 @@ impl<H: hash::Writer> hash::Hash<H> for String {
779822
}
780823
}
781824

782-
#[experimental = "waiting on Equiv stabilization"]
825+
#[allow(deprecated)]
826+
#[deprecated = "Use overloaded `core::cmp::PartialEq`"]
783827
impl<'a, S: Str> Equiv<S> for String {
784828
#[inline]
785829
fn equiv(&self, other: &S) -> bool {
@@ -967,10 +1011,12 @@ mod tests {
9671011
#[test]
9681012
fn test_from_utf8_lossy() {
9691013
let xs = b"hello";
970-
assert_eq!(String::from_utf8_lossy(xs), "hello".into_cow());
1014+
let ys: str::CowString = "hello".into_cow();
1015+
assert_eq!(String::from_utf8_lossy(xs), ys);
9711016

9721017
let xs = "ศไทย中华Việt Nam".as_bytes();
973-
assert_eq!(String::from_utf8_lossy(xs), "ศไทย中华Việt Nam".into_cow());
1018+
let ys: str::CowString = "ศไทย中华Việt Nam".into_cow();
1019+
assert_eq!(String::from_utf8_lossy(xs), ys);
9741020

9751021
let xs = b"Hello\xC2 There\xFF Goodbye";
9761022
assert_eq!(String::from_utf8_lossy(xs),

src/libcollections/vec.rs

+65-9
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,69 @@ impl<T> Extend<T> for Vec<T> {
535535
}
536536
}
537537

538-
#[unstable = "waiting on PartialEq stability"]
539-
impl<T: PartialEq> PartialEq for Vec<T> {
538+
impl<A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B> {
540539
#[inline]
541-
fn eq(&self, other: &Vec<T>) -> bool {
542-
self.as_slice() == other.as_slice()
540+
fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
541+
#[inline]
542+
fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
543+
}
544+
545+
macro_rules! impl_eq {
546+
($lhs:ty, $rhs:ty) => {
547+
impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq<B> {
548+
#[inline]
549+
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
550+
#[inline]
551+
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
552+
}
553+
554+
impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq<A> {
555+
#[inline]
556+
fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
557+
#[inline]
558+
fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) }
559+
}
543560
}
544561
}
545562

563+
impl_eq!(Vec<A>, &'b [B])
564+
impl_eq!(Vec<A>, &'b mut [B])
565+
566+
impl<'a, A, B> PartialEq<Vec<B>> for CowVec<'a, A> where A: PartialEq<B> + Clone {
567+
#[inline]
568+
fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
569+
#[inline]
570+
fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
571+
}
572+
573+
impl<'a, A, B> PartialEq<CowVec<'a, A>> for Vec<B> where A: Clone, B: PartialEq<A> {
574+
#[inline]
575+
fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
576+
#[inline]
577+
fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
578+
}
579+
580+
macro_rules! impl_eq_for_cowvec {
581+
($rhs:ty) => {
582+
impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq<B> + Clone {
583+
#[inline]
584+
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
585+
#[inline]
586+
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
587+
}
588+
589+
impl<'a, 'b, A, B> PartialEq<CowVec<'a, A>> for $rhs where A: Clone, B: PartialEq<A> {
590+
#[inline]
591+
fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
592+
#[inline]
593+
fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
594+
}
595+
}
596+
}
597+
598+
impl_eq_for_cowvec!(&'b [B])
599+
impl_eq_for_cowvec!(&'b mut [B])
600+
546601
#[unstable = "waiting on PartialOrd stability"]
547602
impl<T: PartialOrd> PartialOrd for Vec<T> {
548603
#[inline]
@@ -554,7 +609,8 @@ impl<T: PartialOrd> PartialOrd for Vec<T> {
554609
#[unstable = "waiting on Eq stability"]
555610
impl<T: Eq> Eq for Vec<T> {}
556611

557-
#[experimental]
612+
#[allow(deprecated)]
613+
#[deprecated = "Use overloaded `core::cmp::PartialEq`"]
558614
impl<T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for Vec<T> {
559615
#[inline]
560616
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
@@ -1813,27 +1869,27 @@ mod tests {
18131869
let mut values = vec![1u8,2,3,4,5];
18141870
{
18151871
let slice = values.slice_from_mut(2);
1816-
assert!(slice == &mut [3, 4, 5]);
1872+
assert!(slice == [3, 4, 5]);
18171873
for p in slice.iter_mut() {
18181874
*p += 2;
18191875
}
18201876
}
18211877

1822-
assert!(values.as_slice() == &[1, 2, 5, 6, 7]);
1878+
assert!(values.as_slice() == [1, 2, 5, 6, 7]);
18231879
}
18241880

18251881
#[test]
18261882
fn test_slice_to_mut() {
18271883
let mut values = vec![1u8,2,3,4,5];
18281884
{
18291885
let slice = values.slice_to_mut(2);
1830-
assert!(slice == &mut [1, 2]);
1886+
assert!(slice == [1, 2]);
18311887
for p in slice.iter_mut() {
18321888
*p += 1;
18331889
}
18341890
}
18351891

1836-
assert!(values.as_slice() == &[2, 3, 3, 4, 5]);
1892+
assert!(values.as_slice() == [2, 3, 3, 4, 5]);
18371893
}
18381894

18391895
#[test]

src/libcore/array.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use clone::Clone;
1818
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
1919
use fmt;
2020
use kinds::Copy;
21+
use ops::Deref;
2122
use option::Option;
2223

2324
// macro for implementing n-ary tuple functions and operations
@@ -39,17 +40,37 @@ macro_rules! array_impls {
3940
}
4041

4142
#[unstable = "waiting for PartialEq to stabilize"]
42-
impl<T:PartialEq> PartialEq for [T, ..$N] {
43+
impl<A, B> PartialEq<[B, ..$N]> for [A, ..$N] where A: PartialEq<B> {
4344
#[inline]
44-
fn eq(&self, other: &[T, ..$N]) -> bool {
45+
fn eq(&self, other: &[B, ..$N]) -> bool {
4546
self[] == other[]
4647
}
4748
#[inline]
48-
fn ne(&self, other: &[T, ..$N]) -> bool {
49+
fn ne(&self, other: &[B, ..$N]) -> bool {
4950
self[] != other[]
5051
}
5152
}
5253

54+
impl<'a, A, B, Rhs> PartialEq<Rhs> for [A, ..$N] where
55+
A: PartialEq<B>,
56+
Rhs: Deref<[B]>,
57+
{
58+
#[inline(always)]
59+
fn eq(&self, other: &Rhs) -> bool { PartialEq::eq(self[], &**other) }
60+
#[inline(always)]
61+
fn ne(&self, other: &Rhs) -> bool { PartialEq::ne(self[], &**other) }
62+
}
63+
64+
impl<'a, A, B, Lhs> PartialEq<[B, ..$N]> for Lhs where
65+
A: PartialEq<B>,
66+
Lhs: Deref<[A]>
67+
{
68+
#[inline(always)]
69+
fn eq(&self, other: &[B, ..$N]) -> bool { PartialEq::eq(&**self, other[]) }
70+
#[inline(always)]
71+
fn ne(&self, other: &[B, ..$N]) -> bool { PartialEq::ne(&**self, other[]) }
72+
}
73+
5374
#[unstable = "waiting for Eq to stabilize"]
5475
impl<T:Eq> Eq for [T, ..$N] { }
5576

src/libcore/borrow.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,12 @@ impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
196196
}
197197
}
198198

199-
impl<'a, T, Sized? B> PartialEq for Cow<'a, T, B> where B: PartialEq + ToOwned<T> {
199+
impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
200+
B: PartialEq<C> + ToOwned<T>,
201+
C: ToOwned<U>,
202+
{
200203
#[inline]
201-
fn eq(&self, other: &Cow<'a, T, B>) -> bool {
204+
fn eq(&self, other: &Cow<'b, U, C>) -> bool {
202205
PartialEq::eq(&**self, &**other)
203206
}
204207
}

0 commit comments

Comments
 (0)