1
Fork 0

auto merge of #5234 : pcwalton/rust/equiv, r=pcwalton

r? @nikomatsakis
This commit is contained in:
bors 2013-03-05 12:12:50 -08:00
commit dec599f652
24 changed files with 111 additions and 28 deletions

View file

@ -150,6 +150,14 @@ pub pure fn gt<T:Ord>(v1: &T, v2: &T) -> bool {
(*v1).gt(v2) (*v1).gt(v2)
} }
/// 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`
/// values to look up entries in a container with `~str` keys.
pub trait Equiv<T> {
pure fn equiv(&self, other: &T) -> bool;
}
#[inline(always)] #[inline(always)]
pub pure fn min<T:Ord>(v1: T, v2: T) -> T { pub pure fn min<T:Ord>(v1: T, v2: T) -> T {
if v1 < v2 { v1 } else { v2 } if v1 < v2 { v1 } else { v2 }

View file

@ -10,6 +10,7 @@
//! Container traits //! Container traits
use cmp::Equiv;
use option::Option; use option::Option;
pub trait Container { pub trait Container {

View file

@ -13,7 +13,7 @@
/// Open addressing with linear probing. /// Open addressing with linear probing.
pub mod linear { pub mod linear {
use container::{Container, Mutable, Map, Set}; use container::{Container, Mutable, Map, Set};
use cmp::Eq; use cmp::{Eq, Equiv};
use hash::Hash; use hash::Hash;
use to_bytes::IterBytes; use to_bytes::IterBytes;
use iter::BaseIter; use iter::BaseIter;
@ -107,6 +107,15 @@ pub mod linear {
self.bucket_for_key_with_hash(hash, k) self.bucket_for_key_with_hash(hash, k)
} }
#[inline(always)]
pure fn bucket_for_key_equiv<Q:Hash + IterBytes + Equiv<K>>(
&self,
k: &Q)
-> SearchResult {
let hash = k.hash_keyed(self.k0, self.k1) as uint;
self.bucket_for_key_with_hash_equiv(hash, k)
}
#[inline(always)] #[inline(always)]
pure fn bucket_for_key_with_hash(&self, pure fn bucket_for_key_with_hash(&self,
hash: uint, hash: uint,
@ -122,6 +131,24 @@ pub mod linear {
TableFull TableFull
} }
#[inline(always)]
pure fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self,
hash: uint,
k: &Q)
-> SearchResult {
let _ = for self.bucket_sequence(hash) |i| {
match self.buckets[i] {
Some(ref bkt) => {
if bkt.hash == hash && k.equiv(&bkt.key) {
return FoundEntry(i);
}
},
None => return FoundHole(i)
}
};
TableFull
}
/// Expand the capacity of the array to the next power of two /// Expand the capacity of the array to the next power of two
/// and re-insert each of the existing buckets. /// and re-insert each of the existing buckets.
#[inline(always)] #[inline(always)]
@ -450,6 +477,28 @@ pub mod linear {
None => fail!(fmt!("No entry found for key: %?", k)), None => fail!(fmt!("No entry found for key: %?", k)),
} }
} }
/// Return true if the map contains a value for the specified key,
/// using equivalence
pure fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(
&self,
key: &Q)
-> bool {
match self.bucket_for_key_equiv(key) {
FoundEntry(_) => {true}
TableFull | FoundHole(_) => {false}
}
}
/// Return the value corresponding to the key in the map, using
/// equivalence
pure fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q)
-> Option<&self/V> {
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
}
}
} }
impl<K:Hash + IterBytes + Eq,V:Eq> Eq for LinearMap<K, V> { impl<K:Hash + IterBytes + Eq,V:Eq> Eq for LinearMap<K, V> {

View file

@ -20,7 +20,7 @@
use at_vec; use at_vec;
use cast; use cast;
use char; use char;
use cmp::{TotalOrd, Ordering, Less, Equal, Greater}; use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
use libc; use libc;
use option::{None, Option, Some}; use option::{None, Option, Some};
use ptr; use ptr;
@ -898,6 +898,12 @@ impl Ord for @str {
pure fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) } pure fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) }
} }
#[cfg(notest)]
impl Equiv<~str> for &str {
#[inline(always)]
pure fn equiv(&self, other: &~str) -> bool { eq_slice(*self, *other) }
}
/* /*
Section: Iterating through strings Section: Iterating through strings
*/ */

View file

@ -14,7 +14,7 @@
use container::{Container, Mutable}; use container::{Container, Mutable};
use cast; use cast;
use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater}; use cmp::{Eq, Equiv, Ord, TotalOrd, Ordering, Less, Equal, Greater};
use iter::BaseIter; use iter::BaseIter;
use iter; use iter;
use kinds::Copy; use kinds::Copy;
@ -1572,6 +1572,12 @@ impl<T:Eq> Eq for @[T] {
pure fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) } pure fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) }
} }
#[cfg(notest)]
impl<T:Eq> Equiv<~[T]> for &[T] {
#[inline(always)]
pure fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) }
}
// Lexicographical comparison // Lexicographical comparison
pure fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering { pure fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering {

View file

@ -214,7 +214,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
let mut mt = ast_mt_to_mt(self, rscope, mt); let mut mt = ast_mt_to_mt(self, rscope, mt);
if a_seq_ty.mutbl == ast::m_mutbl || if a_seq_ty.mutbl == ast::m_mutbl ||
a_seq_ty.mutbl == ast::m_const { a_seq_ty.mutbl == ast::m_const {
mt = ty::mt { ty: mt.ty, mutbl: ast::m_mutbl }; mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
} }
return ty::mk_evec(tcx, mt, vst); return ty::mk_evec(tcx, mt, vst);
} }

View file

@ -3112,7 +3112,7 @@ pub impl Parser {
fn parse_trait_ref_list(&self, ket: &token::Token) -> ~[@trait_ref] { fn parse_trait_ref_list(&self, ket: &token::Token) -> ~[@trait_ref] {
self.parse_seq_to_before_end( self.parse_seq_to_before_end(
ket, ket,
seq_sep_none(), seq_sep_trailing_disallowed(token::BINOP(token::PLUS)),
|p| p.parse_trait_ref() |p| p.parse_trait_ref()
) )
} }

View file

@ -600,8 +600,11 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
print_generics(s, generics); print_generics(s, generics);
if traits.len() != 0u { if traits.len() != 0u {
word(s.s, ~":"); word(s.s, ~":");
for traits.each |trait_| { for traits.eachi |i, trait_| {
nbsp(s); nbsp(s);
if i != 0 {
word_space(s, ~"+");
}
print_path(s, trait_.path, false); print_path(s, trait_.path, false);
} }
} }

View file

@ -12,6 +12,6 @@ trait Foo { fn f() -> int; }
trait Bar { fn g() -> int; } trait Bar { fn g() -> int; }
trait Baz { fn h() -> int; } trait Baz { fn h() -> int; }
trait Quux: Foo Bar Baz { } trait Quux: Foo + Bar + Baz { }
impl<T:Foo + Bar + Baz> Quux for T { } impl<T:Foo + Bar + Baz> Quux for T { }

View file

@ -10,7 +10,7 @@
use core::cmp::Eq; use core::cmp::Eq;
pub trait MyNum : Add<Self,Self> Sub<Self,Self> Mul<Self,Self> Eq { pub trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + Eq {
} }
pub struct MyInt { pub struct MyInt {

View file

@ -10,12 +10,15 @@
use core::cmp::Eq; use core::cmp::Eq;
trait Hahaha: Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq //~ ERROR Duplicate supertrait in trait declaration trait Hahaha: Eq + Eq + Eq + Eq + Eq + //~ ERROR Duplicate supertrait
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq Eq {} Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq +
Eq {}
enum Lol = int; enum Lol = int;

View file

@ -0,0 +1,7 @@
fn f(_: &const [int]) {}
fn main() {
let v = [ 1, 2, 3 ];
f(v);
}

View file

@ -17,7 +17,7 @@ extern mod aux(name = "trait_inheritance_auto_xc_2_aux");
use aux::{Foo, Bar, Baz, A}; use aux::{Foo, Bar, Baz, A};
// We want to extend all Foo, Bar, Bazes to Quuxes // We want to extend all Foo, Bar, Bazes to Quuxes
pub trait Quux: Foo Bar Baz { } pub trait Quux: Foo + Bar + Baz { }
impl<T:Foo + Bar + Baz> Quux for T { } impl<T:Foo + Bar + Baz> Quux for T { }
fn f<T:Quux>(a: &T) { fn f<T:Quux>(a: &T) {

View file

@ -16,7 +16,7 @@ trait Foo { fn f() -> int; }
trait Bar { fn g() -> int; } trait Bar { fn g() -> int; }
trait Baz { fn h() -> int; } trait Baz { fn h() -> int; }
trait Quux: Foo Bar Baz { } trait Quux: Foo + Bar + Baz { }
struct A { x: int } struct A { x: int }

View file

@ -13,7 +13,7 @@
trait A { fn a(&self) -> int; } trait A { fn a(&self) -> int; }
trait B: A { fn b(&self) -> int; } trait B: A { fn b(&self) -> int; }
trait C: A { fn c(&self) -> int; } trait C: A { fn c(&self) -> int; }
trait D: B C { fn d(&self) -> int; } trait D: B + C { fn d(&self) -> int; }
struct S { bogus: () } struct S { bogus: () }

View file

@ -16,9 +16,9 @@ use core::num::NumCast::from;
extern mod std; extern mod std;
use std::cmp::FuzzyEq; use std::cmp::FuzzyEq;
pub trait NumExt: NumCast Eq Ord {} pub trait NumExt: NumCast + Eq + Ord {}
pub trait FloatExt: NumExt FuzzyEq<Self> {} pub trait FloatExt: NumExt + FuzzyEq<Self> {}
fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > from(1) } fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > from(1) }
fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > from(1) } fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > from(1) }

View file

@ -19,7 +19,7 @@ trait Num {
fn gt(&self, other: &Self) -> bool; fn gt(&self, other: &Self) -> bool;
} }
pub trait NumExt: Num NumCast { } pub trait NumExt: Num + NumCast { }
fn greater_than_one<T:NumExt>(n: &T) -> bool { fn greater_than_one<T:NumExt>(n: &T) -> bool {
n.gt(&from(1)) n.gt(&from(1))

View file

@ -11,7 +11,7 @@
use core::cmp::Ord; use core::cmp::Ord;
use core::num::NumCast::from; use core::num::NumCast::from;
pub trait NumExt: NumCast Ord { } pub trait NumExt: NumCast + Ord { }
fn greater_than_one<T:NumExt>(n: &T) -> bool { fn greater_than_one<T:NumExt>(n: &T) -> bool {
*n > from(1) *n > from(1)

View file

@ -38,7 +38,7 @@ impl TypeExt for f64 {}
impl TypeExt for float {} impl TypeExt for float {}
pub trait NumExt: TypeExt Eq Ord NumCast {} pub trait NumExt: TypeExt + Eq + Ord + NumCast {}
impl NumExt for u8 {} impl NumExt for u8 {}
impl NumExt for u16 {} impl NumExt for u16 {}
@ -94,7 +94,7 @@ impl IntegerExt for i64 {}
impl IntegerExt for int {} impl IntegerExt for int {}
pub trait FloatExt: NumExt FuzzyEq<Self> {} pub trait FloatExt: NumExt + FuzzyEq<Self> {}
impl FloatExt for f32 {} impl FloatExt for f32 {}
impl FloatExt for f64 {} impl FloatExt for f64 {}

View file

@ -11,7 +11,7 @@
use core::cmp::{Eq, Ord}; use core::cmp::{Eq, Ord};
use core::num::NumCast::from; use core::num::NumCast::from;
pub trait NumExt: Eq Ord NumCast {} pub trait NumExt: Eq + Ord + NumCast {}
impl NumExt for f32 {} impl NumExt for f32 {}

View file

@ -11,7 +11,7 @@
use core::cmp::{Eq, Ord}; use core::cmp::{Eq, Ord};
use core::num::NumCast::from; use core::num::NumCast::from;
pub trait NumExt: Eq NumCast {} pub trait NumExt: Eq + NumCast {}
impl NumExt for f32 {} impl NumExt for f32 {}
impl NumExt for int {} impl NumExt for int {}

View file

@ -10,7 +10,7 @@
use core::cmp::Eq; use core::cmp::Eq;
trait MyNum : Add<Self,Self> Sub<Self,Self> Mul<Self,Self> Eq { } trait MyNum : Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + Eq { }
struct MyInt { val: int } struct MyInt { val: int }

View file

@ -14,7 +14,7 @@ trait MyNum {
static fn from_int(int) -> Self; static fn from_int(int) -> Self;
} }
pub trait NumExt: MyEq MyNum { } pub trait NumExt: MyEq + MyNum { }
struct S { v: int } struct S { v: int }

View file

@ -12,7 +12,7 @@ trait Foo { fn f() -> int; }
trait Bar { fn g() -> int; } trait Bar { fn g() -> int; }
trait Baz { fn h() -> int; } trait Baz { fn h() -> int; }
trait Quux: Foo Bar Baz { } trait Quux: Foo + Bar + Baz { }
struct A { x: int } struct A { x: int }