Skip to content

Commit dec599f

Browse files
committed
auto merge of #5234 : pcwalton/rust/equiv, r=pcwalton
r? @nikomatsakis
2 parents 4c8e12e + 2fa2ad5 commit dec599f

24 files changed

+111
-28
lines changed

src/libcore/cmp.rs

+8
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ pub pure fn gt<T:Ord>(v1: &T, v2: &T) -> bool {
150150
(*v1).gt(v2)
151151
}
152152

153+
/// The equivalence relation. Two values may be equivalent even if they are
154+
/// of different types. The most common use case for this relation is
155+
/// container types; e.g. it is often desirable to be able to use `&str`
156+
/// values to look up entries in a container with `~str` keys.
157+
pub trait Equiv<T> {
158+
pure fn equiv(&self, other: &T) -> bool;
159+
}
160+
153161
#[inline(always)]
154162
pub pure fn min<T:Ord>(v1: T, v2: T) -> T {
155163
if v1 < v2 { v1 } else { v2 }

src/libcore/container.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
//! Container traits
1212
13+
use cmp::Equiv;
1314
use option::Option;
1415

1516
pub trait Container {

src/libcore/hashmap.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/// Open addressing with linear probing.
1414
pub mod linear {
1515
use container::{Container, Mutable, Map, Set};
16-
use cmp::Eq;
16+
use cmp::{Eq, Equiv};
1717
use hash::Hash;
1818
use to_bytes::IterBytes;
1919
use iter::BaseIter;
@@ -107,6 +107,15 @@ pub mod linear {
107107
self.bucket_for_key_with_hash(hash, k)
108108
}
109109

110+
#[inline(always)]
111+
pure fn bucket_for_key_equiv<Q:Hash + IterBytes + Equiv<K>>(
112+
&self,
113+
k: &Q)
114+
-> SearchResult {
115+
let hash = k.hash_keyed(self.k0, self.k1) as uint;
116+
self.bucket_for_key_with_hash_equiv(hash, k)
117+
}
118+
110119
#[inline(always)]
111120
pure fn bucket_for_key_with_hash(&self,
112121
hash: uint,
@@ -122,6 +131,24 @@ pub mod linear {
122131
TableFull
123132
}
124133

134+
#[inline(always)]
135+
pure fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self,
136+
hash: uint,
137+
k: &Q)
138+
-> SearchResult {
139+
let _ = for self.bucket_sequence(hash) |i| {
140+
match self.buckets[i] {
141+
Some(ref bkt) => {
142+
if bkt.hash == hash && k.equiv(&bkt.key) {
143+
return FoundEntry(i);
144+
}
145+
},
146+
None => return FoundHole(i)
147+
}
148+
};
149+
TableFull
150+
}
151+
125152
/// Expand the capacity of the array to the next power of two
126153
/// and re-insert each of the existing buckets.
127154
#[inline(always)]
@@ -450,6 +477,28 @@ pub mod linear {
450477
None => fail!(fmt!("No entry found for key: %?", k)),
451478
}
452479
}
480+
481+
/// Return true if the map contains a value for the specified key,
482+
/// using equivalence
483+
pure fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(
484+
&self,
485+
key: &Q)
486+
-> bool {
487+
match self.bucket_for_key_equiv(key) {
488+
FoundEntry(_) => {true}
489+
TableFull | FoundHole(_) => {false}
490+
}
491+
}
492+
493+
/// Return the value corresponding to the key in the map, using
494+
/// equivalence
495+
pure fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q)
496+
-> Option<&self/V> {
497+
match self.bucket_for_key_equiv(k) {
498+
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
499+
TableFull | FoundHole(_) => None,
500+
}
501+
}
453502
}
454503

455504
impl<K:Hash + IterBytes + Eq,V:Eq> Eq for LinearMap<K, V> {

src/libcore/str.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use at_vec;
2121
use cast;
2222
use char;
23-
use cmp::{TotalOrd, Ordering, Less, Equal, Greater};
23+
use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
2424
use libc;
2525
use option::{None, Option, Some};
2626
use ptr;
@@ -898,6 +898,12 @@ impl Ord for @str {
898898
pure fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) }
899899
}
900900

901+
#[cfg(notest)]
902+
impl Equiv<~str> for &str {
903+
#[inline(always)]
904+
pure fn equiv(&self, other: &~str) -> bool { eq_slice(*self, *other) }
905+
}
906+
901907
/*
902908
Section: Iterating through strings
903909
*/

src/libcore/vec.rs

+7-1
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, Ord, TotalOrd, Ordering, Less, Equal, Greater};
17+
use cmp::{Eq, Equiv, Ord, TotalOrd, Ordering, Less, Equal, Greater};
1818
use iter::BaseIter;
1919
use iter;
2020
use kinds::Copy;
@@ -1572,6 +1572,12 @@ impl<T:Eq> Eq for @[T] {
15721572
pure fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) }
15731573
}
15741574

1575+
#[cfg(notest)]
1576+
impl<T:Eq> Equiv<~[T]> for &[T] {
1577+
#[inline(always)]
1578+
pure fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) }
1579+
}
1580+
15751581
// Lexicographical comparison
15761582

15771583
pure fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering {

src/librustc/middle/typeck/astconv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
214214
let mut mt = ast_mt_to_mt(self, rscope, mt);
215215
if a_seq_ty.mutbl == ast::m_mutbl ||
216216
a_seq_ty.mutbl == ast::m_const {
217-
mt = ty::mt { ty: mt.ty, mutbl: ast::m_mutbl };
217+
mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
218218
}
219219
return ty::mk_evec(tcx, mt, vst);
220220
}

src/libsyntax/parse/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3112,7 +3112,7 @@ pub impl Parser {
31123112
fn parse_trait_ref_list(&self, ket: &token::Token) -> ~[@trait_ref] {
31133113
self.parse_seq_to_before_end(
31143114
ket,
3115-
seq_sep_none(),
3115+
seq_sep_trailing_disallowed(token::BINOP(token::PLUS)),
31163116
|p| p.parse_trait_ref()
31173117
)
31183118
}

src/libsyntax/print/pprust.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -600,8 +600,11 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
600600
print_generics(s, generics);
601601
if traits.len() != 0u {
602602
word(s.s, ~":");
603-
for traits.each |trait_| {
603+
for traits.eachi |i, trait_| {
604604
nbsp(s);
605+
if i != 0 {
606+
word_space(s, ~"+");
607+
}
605608
print_path(s, trait_.path, false);
606609
}
607610
}

src/test/auxiliary/trait_inheritance_auto_xc_aux.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ trait Foo { fn f() -> int; }
1212
trait Bar { fn g() -> int; }
1313
trait Baz { fn h() -> int; }
1414

15-
trait Quux: Foo Bar Baz { }
15+
trait Quux: Foo + Bar + Baz { }
1616

1717
impl<T:Foo + Bar + Baz> Quux for T { }

src/test/auxiliary/trait_inheritance_overloading_xc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use core::cmp::Eq;
1212

13-
pub trait MyNum : Add<Self,Self> Sub<Self,Self> Mul<Self,Self> Eq {
13+
pub trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + Eq {
1414
}
1515

1616
pub struct MyInt {

src/test/compile-fail/issue-3953.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111
use core::cmp::Eq;
1212

13-
trait Hahaha: Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq //~ ERROR Duplicate supertrait in trait declaration
14-
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq
15-
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq
16-
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq
17-
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq
18-
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq {}
13+
trait Hahaha: Eq + Eq + Eq + Eq + Eq + //~ ERROR Duplicate supertrait
14+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
15+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
16+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
17+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
18+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
19+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
20+
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
21+
Eq {}
1922

2023
enum Lol = int;
2124

src/test/run-pass/const-vec-syntax.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn f(_: &const [int]) {}
2+
3+
fn main() {
4+
let v = [ 1, 2, 3 ];
5+
f(v);
6+
}
7+

src/test/run-pass/trait-inheritance-auto-xc-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extern mod aux(name = "trait_inheritance_auto_xc_2_aux");
1717
use aux::{Foo, Bar, Baz, A};
1818

1919
// We want to extend all Foo, Bar, Bazes to Quuxes
20-
pub trait Quux: Foo Bar Baz { }
20+
pub trait Quux: Foo + Bar + Baz { }
2121
impl<T:Foo + Bar + Baz> Quux for T { }
2222

2323
fn f<T:Quux>(a: &T) {

src/test/run-pass/trait-inheritance-auto.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ trait Foo { fn f() -> int; }
1616
trait Bar { fn g() -> int; }
1717
trait Baz { fn h() -> int; }
1818

19-
trait Quux: Foo Bar Baz { }
19+
trait Quux: Foo + Bar + Baz { }
2020

2121
struct A { x: int }
2222

src/test/run-pass/trait-inheritance-diamond.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
trait A { fn a(&self) -> int; }
1414
trait B: A { fn b(&self) -> int; }
1515
trait C: A { fn c(&self) -> int; }
16-
trait D: B C { fn d(&self) -> int; }
16+
trait D: B + C { fn d(&self) -> int; }
1717

1818
struct S { bogus: () }
1919

src/test/run-pass/trait-inheritance-num.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use core::num::NumCast::from;
1616
extern mod std;
1717
use std::cmp::FuzzyEq;
1818

19-
pub trait NumExt: NumCast Eq Ord {}
19+
pub trait NumExt: NumCast + Eq + Ord {}
2020

21-
pub trait FloatExt: NumExt FuzzyEq<Self> {}
21+
pub trait FloatExt: NumExt + FuzzyEq<Self> {}
2222

2323
fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > from(1) }
2424
fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > from(1) }

src/test/run-pass/trait-inheritance-num0.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ trait Num {
1919
fn gt(&self, other: &Self) -> bool;
2020
}
2121

22-
pub trait NumExt: Num NumCast { }
22+
pub trait NumExt: Num + NumCast { }
2323

2424
fn greater_than_one<T:NumExt>(n: &T) -> bool {
2525
n.gt(&from(1))

src/test/run-pass/trait-inheritance-num1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use core::cmp::Ord;
1212
use core::num::NumCast::from;
1313

14-
pub trait NumExt: NumCast Ord { }
14+
pub trait NumExt: NumCast + Ord { }
1515

1616
fn greater_than_one<T:NumExt>(n: &T) -> bool {
1717
*n > from(1)

src/test/run-pass/trait-inheritance-num2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl TypeExt for f64 {}
3838
impl TypeExt for float {}
3939

4040

41-
pub trait NumExt: TypeExt Eq Ord NumCast {}
41+
pub trait NumExt: TypeExt + Eq + Ord + NumCast {}
4242

4343
impl NumExt for u8 {}
4444
impl NumExt for u16 {}
@@ -94,7 +94,7 @@ impl IntegerExt for i64 {}
9494
impl IntegerExt for int {}
9595

9696

97-
pub trait FloatExt: NumExt FuzzyEq<Self> {}
97+
pub trait FloatExt: NumExt + FuzzyEq<Self> {}
9898

9999
impl FloatExt for f32 {}
100100
impl FloatExt for f64 {}

src/test/run-pass/trait-inheritance-num3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use core::cmp::{Eq, Ord};
1212
use core::num::NumCast::from;
1313

14-
pub trait NumExt: Eq Ord NumCast {}
14+
pub trait NumExt: Eq + Ord + NumCast {}
1515

1616
impl NumExt for f32 {}
1717

src/test/run-pass/trait-inheritance-num5.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use core::cmp::{Eq, Ord};
1212
use core::num::NumCast::from;
1313

14-
pub trait NumExt: Eq NumCast {}
14+
pub trait NumExt: Eq + NumCast {}
1515

1616
impl NumExt for f32 {}
1717
impl NumExt for int {}

src/test/run-pass/trait-inheritance-overloading.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use core::cmp::Eq;
1212

13-
trait MyNum : Add<Self,Self> Sub<Self,Self> Mul<Self,Self> Eq { }
13+
trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + Eq { }
1414

1515
struct MyInt { val: int }
1616

src/test/run-pass/trait-inheritance-static2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait MyNum {
1414
static fn from_int(int) -> Self;
1515
}
1616

17-
pub trait NumExt: MyEq MyNum { }
17+
pub trait NumExt: MyEq + MyNum { }
1818

1919
struct S { v: int }
2020

src/test/run-pass/trait-inheritance2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ trait Foo { fn f() -> int; }
1212
trait Bar { fn g() -> int; }
1313
trait Baz { fn h() -> int; }
1414

15-
trait Quux: Foo Bar Baz { }
15+
trait Quux: Foo + Bar + Baz { }
1616

1717
struct A { x: int }
1818

0 commit comments

Comments
 (0)