Migrate std::map to use core:#️⃣:Hash trait. Disable many hokey hashes.

This commit is contained in:
Graydon Hoare 2012-09-07 17:24:02 -07:00
parent f5093dff7b
commit 5d823d46ad
18 changed files with 741 additions and 402 deletions

View File

@ -64,7 +64,7 @@ impl <A: IterBytes> A: Hash {
pure fn hash_keyed(k0: u64, k1: u64) -> u64 {
unchecked {
let s = &State(k0, k1);
for self.iter_le_bytes |bytes| {
for self.iter_bytes(true) |bytes| {
s.input(bytes);
}
s.result_u64()
@ -79,8 +79,8 @@ pure fn hash_keyed_2<A: IterBytes,
k0: u64, k1: u64) -> u64 {
unchecked {
let s = &State(k0, k1);
for a.iter_le_bytes |bytes| { s.input(bytes); }
for b.iter_le_bytes |bytes| { s.input(bytes); }
for a.iter_bytes(true) |bytes| { s.input(bytes); }
for b.iter_bytes(true) |bytes| { s.input(bytes); }
s.result_u64()
}
}
@ -91,9 +91,9 @@ pure fn hash_keyed_3<A: IterBytes,
k0: u64, k1: u64) -> u64 {
unchecked {
let s = &State(k0, k1);
for a.iter_le_bytes |bytes| { s.input(bytes); }
for b.iter_le_bytes |bytes| { s.input(bytes); }
for c.iter_le_bytes |bytes| { s.input(bytes); }
for a.iter_bytes(true) |bytes| { s.input(bytes); }
for b.iter_bytes(true) |bytes| { s.input(bytes); }
for c.iter_bytes(true) |bytes| { s.input(bytes); }
s.result_u64()
}
}
@ -105,10 +105,10 @@ pure fn hash_keyed_4<A: IterBytes,
k0: u64, k1: u64) -> u64 {
unchecked {
let s = &State(k0, k1);
for a.iter_le_bytes |bytes| { s.input(bytes); }
for b.iter_le_bytes |bytes| { s.input(bytes); }
for c.iter_le_bytes |bytes| { s.input(bytes); }
for d.iter_le_bytes |bytes| { s.input(bytes); }
for a.iter_bytes(true) |bytes| { s.input(bytes); }
for b.iter_bytes(true) |bytes| { s.input(bytes); }
for c.iter_bytes(true) |bytes| { s.input(bytes); }
for d.iter_bytes(true) |bytes| { s.input(bytes); }
s.result_u64()
}
}
@ -121,11 +121,11 @@ pure fn hash_keyed_5<A: IterBytes,
k0: u64, k1: u64) -> u64 {
unchecked {
let s = &State(k0, k1);
for a.iter_le_bytes |bytes| { s.input(bytes); }
for b.iter_le_bytes |bytes| { s.input(bytes); }
for c.iter_le_bytes |bytes| { s.input(bytes); }
for d.iter_le_bytes |bytes| { s.input(bytes); }
for e.iter_le_bytes |bytes| { s.input(bytes); }
for a.iter_bytes(true) |bytes| { s.input(bytes); }
for b.iter_bytes(true) |bytes| { s.input(bytes); }
for c.iter_bytes(true) |bytes| { s.input(bytes); }
for d.iter_bytes(true) |bytes| { s.input(bytes); }
for e.iter_bytes(true) |bytes| { s.input(bytes); }
s.result_u64()
}
}

View File

@ -7,221 +7,273 @@ use io::Writer;
type Cb = fn(buf: &[const u8]) -> bool;
trait IterBytes {
fn iter_le_bytes(f: Cb);
fn iter_be_bytes(f: Cb);
fn iter_bytes(lsb0: bool, f: Cb);
}
impl u8: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
fn iter_bytes(_lsb0: bool, f: Cb) {
f([
self,
]);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
f([
self as u8
self
]);
}
}
impl u16: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
f([
self as u8,
(self >> 8) as u8
]);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
f([
(self >> 8) as u8,
self as u8
]);
fn iter_bytes(lsb0: bool, f: Cb) {
if lsb0 {
f([
self as u8,
(self >> 8) as u8
]);
} else {
f([
(self >> 8) as u8,
self as u8
]);
}
}
}
impl u32: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
f([
self as u8,
(self >> 8) as u8,
(self >> 16) as u8,
(self >> 24) as u8,
]);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
f([
(self >> 24) as u8,
(self >> 16) as u8,
(self >> 8) as u8,
self as u8
]);
fn iter_bytes(lsb0: bool, f: Cb) {
if lsb0 {
f([
self as u8,
(self >> 8) as u8,
(self >> 16) as u8,
(self >> 24) as u8,
]);
} else {
f([
(self >> 24) as u8,
(self >> 16) as u8,
(self >> 8) as u8,
self as u8
]);
}
}
}
impl u64: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
f([
self as u8,
(self >> 8) as u8,
(self >> 16) as u8,
(self >> 24) as u8,
(self >> 32) as u8,
(self >> 40) as u8,
(self >> 48) as u8,
(self >> 56) as u8
]);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
f([
(self >> 56) as u8,
(self >> 48) as u8,
(self >> 40) as u8,
(self >> 32) as u8,
(self >> 24) as u8,
(self >> 16) as u8,
(self >> 8) as u8,
self as u8
]);
fn iter_bytes(lsb0: bool, f: Cb) {
if lsb0 {
f([
self as u8,
(self >> 8) as u8,
(self >> 16) as u8,
(self >> 24) as u8,
(self >> 32) as u8,
(self >> 40) as u8,
(self >> 48) as u8,
(self >> 56) as u8
]);
} else {
f([
(self >> 56) as u8,
(self >> 48) as u8,
(self >> 40) as u8,
(self >> 32) as u8,
(self >> 24) as u8,
(self >> 16) as u8,
(self >> 8) as u8,
self as u8
]);
}
}
}
impl i8: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u8).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u8).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl i16: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u16).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u16).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u16).iter_bytes(lsb0, f)
}
}
impl i32: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u32).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u32).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u32).iter_bytes(lsb0, f)
}
}
impl i64: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u64).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u64).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u64).iter_bytes(lsb0, f)
}
}
#[cfg(target_word_size = "32")]
impl uint: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u32).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u32).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u32).iter_bytes(lsb0, f)
}
}
#[cfg(target_word_size = "64")]
impl uint: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as u64).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as u64).iter_be_bytes(f) }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as u64).iter_bytes(lsb0, f)
}
}
impl int: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { (self as uint).iter_le_bytes(f) }
#[inline(always)]
fn iter_be_bytes(f: Cb) { (self as uint).iter_be_bytes(f) }
}
impl ~[const u8]: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { f(self); }
#[inline(always)]
fn iter_be_bytes(f: Cb) { f(self); }
}
impl @[const u8]: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) { f(self); }
#[inline(always)]
fn iter_be_bytes(f: Cb) { f(self); }
fn iter_bytes(lsb0: bool, f: Cb) {
(self as uint).iter_bytes(lsb0, f)
}
}
impl<A: IterBytes> &[const A]: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
fn iter_bytes(lsb0: bool, f: Cb) {
for self.each |elt| {
do elt.iter_le_bytes |bytes| {
do elt.iter_bytes(lsb0) |bytes| {
f(bytes)
}
}
}
}
// Move this to vec, probably.
fn borrow<A>(a: &x/[const A]) -> &x/[const A] {
a
}
impl<A: IterBytes> ~[const A]: IterBytes {
#[inline(always)]
fn iter_be_bytes(f: Cb) {
for self.each |elt| {
do elt.iter_be_bytes |bytes| {
f(bytes)
}
}
fn iter_bytes(lsb0: bool, f: Cb) {
borrow(self).iter_bytes(lsb0, f)
}
}
fn iter_le_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, f: Cb) {
let mut flag = true;
a.iter_le_bytes(|bytes| {flag = f(bytes); flag});
if !flag { return; }
b.iter_le_bytes(|bytes| {flag = f(bytes); flag});
impl<A: IterBytes> @[const A]: IterBytes {
#[inline(always)]
fn iter_bytes(lsb0: bool, f: Cb) {
borrow(self).iter_bytes(lsb0, f)
}
}
fn iter_be_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B, f: Cb) {
fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_be_bytes(|bytes| {flag = f(bytes); flag});
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_be_bytes(|bytes| {flag = f(bytes); flag});
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
fn iter_le_bytes_3<A: IterBytes,
B: IterBytes,
C: IterBytes>(a: &A, b: &B, c: &C, f: Cb) {
fn iter_bytes_3<A: IterBytes,
B: IterBytes,
C: IterBytes>(a: &A, b: &B, c: &C,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_le_bytes(|bytes| {flag = f(bytes); flag});
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_le_bytes(|bytes| { flag = f(bytes); flag});
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
c.iter_le_bytes(|bytes| {flag = f(bytes); flag});
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
fn iter_be_bytes_3<A: IterBytes,
B: IterBytes,
C: IterBytes>(a: &A, b: &B, c: &C, f: Cb) {
fn iter_bytes_4<A: IterBytes,
B: IterBytes,
C: IterBytes,
D: IterBytes>(a: &A, b: &B, c: &C,
d: &D,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_be_bytes(|bytes| {flag = f(bytes); flag});
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_be_bytes(|bytes| {flag = f(bytes); flag});
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
c.iter_be_bytes(|bytes| {flag = f(bytes); flag});
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
fn iter_bytes_5<A: IterBytes,
B: IterBytes,
C: IterBytes,
D: IterBytes,
E: IterBytes>(a: &A, b: &B, c: &C,
d: &D, e: &E,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
fn iter_bytes_6<A: IterBytes,
B: IterBytes,
C: IterBytes,
D: IterBytes,
E: IterBytes,
F: IterBytes>(a: &A, b: &B, c: &C,
d: &D, e: &E, f: &F,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
fn iter_bytes_7<A: IterBytes,
B: IterBytes,
C: IterBytes,
D: IterBytes,
E: IterBytes,
F: IterBytes,
G: IterBytes>(a: &A, b: &B, c: &C,
d: &D, e: &E, f: &F,
g: &G,
lsb0: bool, z: Cb) {
let mut flag = true;
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
if !flag { return; }
g.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}
impl &str: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
fn iter_bytes(_lsb0: bool, f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
@ -230,13 +282,7 @@ impl &str: IterBytes {
impl ~str: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
fn iter_bytes(_lsb0: bool, f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
@ -245,48 +291,41 @@ impl ~str: IterBytes {
impl @str: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
fn iter_bytes(_lsb0: bool, f: Cb) {
do str::byte_slice(self) |bytes| {
f(bytes);
}
}
}
impl<A: IterBytes> Option<A>: IterBytes {
#[inline(always)]
fn iter_bytes(lsb0: bool, f: Cb) {
match self {
Some(a) => iter_bytes_2(&0u8, &a, lsb0, f),
None => 1u8.iter_bytes(lsb0, f)
}
}
}
impl<A: IterBytes> &A: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
(*self).iter_le_bytes(f);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
(*self).iter_be_bytes(f);
fn iter_bytes(lsb0: bool, f: Cb) {
(*self).iter_bytes(lsb0, f);
}
}
impl<A: IterBytes> @A: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
(*self).iter_le_bytes(f);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
(*self).iter_be_bytes(f);
fn iter_bytes(lsb0: bool, f: Cb) {
(*self).iter_bytes(lsb0, f);
}
}
impl<A: IterBytes> ~A: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
(*self).iter_le_bytes(f);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
(*self).iter_be_bytes(f);
fn iter_bytes(lsb0: bool, f: Cb) {
(*self).iter_bytes(lsb0, f);
}
}
@ -294,35 +333,22 @@ impl<A: IterBytes> ~A: IterBytes {
// to the target; it just gives you the pointer-bytes.
impl<A> *A: IterBytes {
#[inline(always)]
fn iter_le_bytes(f: Cb) {
(self as uint).iter_le_bytes(f);
}
#[inline(always)]
fn iter_be_bytes(f: Cb) {
(self as uint).iter_be_bytes(f);
fn iter_bytes(lsb0: bool, f: Cb) {
(self as uint).iter_bytes(lsb0, f);
}
}
trait ToBytes {
fn to_le_bytes() -> ~[u8];
fn to_be_bytes() -> ~[u8];
fn to_bytes(lsb0: bool) -> ~[u8];
}
impl<A: IterBytes> A: ToBytes {
fn to_le_bytes() -> ~[u8] {
fn to_bytes(lsb0: bool) -> ~[u8] {
let buf = io::mem_buffer();
for self.iter_le_bytes |bytes| {
for self.iter_bytes(lsb0) |bytes| {
buf.write(bytes)
}
io::mem_buffer_buf(buf)
}
fn to_be_bytes() -> ~[u8] {
let buf = io::mem_buffer();
for self.iter_be_bytes |bytes| {
buf.write(bytes)
}
io::mem_buffer_buf(buf)
}
}

View File

@ -19,21 +19,12 @@ export hash_from_vec, hash_from_strs, hash_from_bytes;
export hash_from_ints, hash_from_uints;
export vec_from_set;
/**
* A function that returns a hash of a value
*
* The hash should concentrate entropy in the lower bits.
*/
type hashfn<K> = fn~(key: &K) -> uint;
type eqfn<K> = fn~(key1: &K, key2: &K) -> bool;
/// A convenience type to treat a hashmap as a set
type set<K> = hashmap<K, ()>;
type set<K:Eq IterBytes Hash> = hashmap<K, ()>;
type hashmap<K, V> = chained::t<K, V>;
type hashmap<K:Eq IterBytes Hash, V> = chained::t<K, V>;
trait map<K: copy, V: copy> {
trait map<K:Eq IterBytes Hash copy, V: copy> {
/// Return the number of elements in the map
pure fn size() -> uint;
@ -119,14 +110,12 @@ mod chained {
mut next: Option<@entry<K, V>>
}
struct hashmap_<K, V> {
struct hashmap_<K:Eq IterBytes Hash, V> {
mut count: uint,
mut chains: ~[mut Option<@entry<K,V>>],
hasher: hashfn<K>,
eqer: eqfn<K>
mut chains: ~[mut Option<@entry<K,V>>]
}
type t<K, V> = @hashmap_<K, V>;
type t<K:Eq IterBytes Hash, V> = @hashmap_<K, V>;
enum search_result<K, V> {
not_found,
@ -134,7 +123,7 @@ mod chained {
found_after(@entry<K,V>, @entry<K,V>)
}
priv impl<K, V: copy> t<K, V> {
priv impl<K:Eq IterBytes Hash, V: copy> t<K, V> {
pure fn search_rem(k: &K, h: uint, idx: uint,
e_root: @entry<K,V>) -> search_result<K,V> {
let mut e0 = e_root;
@ -149,7 +138,7 @@ mod chained {
Some(e1) => {
comp += 1u;
unchecked {
if e1.hash == h && self.eqer(&e1.key, k) {
if e1.hash == h && e1.key == *k {
debug!("search_tbl: present, comp %u, \
hash %u, idx %u",
comp, h, idx);
@ -173,7 +162,7 @@ mod chained {
}
Some(e) => {
unchecked {
if e.hash == h && self.eqer(&e.key, k) {
if e.hash == h && e.key == *k {
debug!("search_tbl: present, comp %u, hash %u, \
idx %u", 1u, h, idx);
return found_first(idx, e);
@ -218,7 +207,7 @@ mod chained {
}
}
impl<K: copy, V: copy> t<K, V>: map<K, V> {
impl<K:Eq IterBytes Hash copy, V: copy> t<K, V>: map<K, V> {
pure fn size() -> uint { self.count }
fn contains_key(+k: K) -> bool {
@ -226,7 +215,7 @@ mod chained {
}
fn contains_key_ref(k: &K) -> bool {
let hash = self.hasher(k);
let hash = k.hash_keyed(0,0) as uint;
match self.search_tbl(k, hash) {
not_found => false,
found_first(*) | found_after(*) => true
@ -234,7 +223,7 @@ mod chained {
}
fn insert(+k: K, +v: V) -> bool {
let hash = self.hasher(&k);
let hash = k.hash_keyed(0,0) as uint;
match self.search_tbl(&k, hash) {
not_found => {
self.count += 1u;
@ -277,7 +266,7 @@ mod chained {
pure fn find(+k: K) -> Option<V> {
unchecked {
match self.search_tbl(&k, self.hasher(&k)) {
match self.search_tbl(&k, k.hash_keyed(0,0) as uint) {
not_found => None,
found_first(_, entry) => Some(entry.value),
found_after(_, entry) => Some(entry.value)
@ -294,7 +283,7 @@ mod chained {
}
fn remove(+k: K) -> bool {
match self.search_tbl(&k, self.hasher(&k)) {
match self.search_tbl(&k, k.hash_keyed(0,0) as uint) {
not_found => false,
found_first(idx, entry) => {
self.count -= 1u;
@ -341,7 +330,7 @@ mod chained {
}
}
impl<K: copy ToStr, V: ToStr copy> t<K, V>: ToStr {
impl<K:Eq IterBytes Hash copy ToStr, V: ToStr copy> t<K, V>: ToStr {
fn to_writer(wr: io::Writer) {
if self.count == 0u {
wr.write_str(~"{}");
@ -367,7 +356,7 @@ mod chained {
}
}
impl<K: copy, V: copy> t<K, V>: ops::Index<K, V> {
impl<K:Eq IterBytes Hash copy, V: copy> t<K, V>: ops::Index<K, V> {
pure fn index(&&k: K) -> V {
unchecked {
self.get(k)
@ -379,11 +368,9 @@ mod chained {
vec::to_mut(vec::from_elem(nchains, None))
}
fn mk<K, V: copy>(+hasher: hashfn<K>, +eqer: eqfn<K>) -> t<K,V> {
fn mk<K:Eq IterBytes Hash, V: copy>() -> t<K,V> {
let slf: t<K, V> = @hashmap_ {count: 0u,
chains: chains(initial_capacity),
hasher: hasher,
eqer: eqer};
chains: chains(initial_capacity)};
slf
}
}
@ -392,56 +379,49 @@ mod chained {
Function: hashmap
Construct a hashmap.
Parameters:
hasher - The hash function for key type K
eqer - The equality function for key type K
*/
fn hashmap<K: const, V: copy>(+hasher: hashfn<K>, +eqer: eqfn<K>)
fn hashmap<K:Eq IterBytes Hash const, V: copy>()
-> hashmap<K, V> {
chained::mk(hasher, eqer)
chained::mk()
}
/// Construct a hashmap for string-slice keys
fn str_slice_hash<V: copy>() -> hashmap<&str, V> {
return hashmap(|s| hash::hash_str(*s) as uint,
|a,b| str::eq_slice(*a, *b));
return hashmap();
}
/// Construct a hashmap for string keys
fn str_hash<V: copy>() -> hashmap<~str, V> {
return hashmap(str::hash, str::eq);
return hashmap();
}
/// Construct a hashmap for boxed string keys
fn box_str_hash<V: copy>() -> hashmap<@~str, V> {
hashmap(|x: &@~str| str::hash(&**x),
|x: &@~str, y: &@~str| str::eq(&**x, &**y))
hashmap()
}
/// Construct a hashmap for byte string keys
fn bytes_hash<V: copy>() -> hashmap<~[u8], V> {
return hashmap(vec::u8::hash, vec::u8::eq);
return hashmap();
}
/// Construct a hashmap for int keys
fn int_hash<V: copy>() -> hashmap<int, V> {
return hashmap(|x| { int::hash(*x) }, |x, y| { int::eq(*x, *y)});
return hashmap();
}
/// Construct a hashmap for uint keys
fn uint_hash<V: copy>() -> hashmap<uint, V> {
return hashmap(|x| { uint::hash(*x) }, |x, y| { uint::eq(*x, *y) } );
return hashmap();
}
/// Convenience function for adding keys to a hashmap with nil type keys
fn set_add<K: const copy>(set: set<K>, +key: K) -> bool {
fn set_add<K:Eq IterBytes Hash const copy>(set: set<K>, +key: K) -> bool {
set.insert(key, ())
}
/// Convert a set into a vector.
fn vec_from_set<T: copy>(s: set<T>) -> ~[T] {
fn vec_from_set<T:Eq IterBytes Hash copy>(s: set<T>) -> ~[T] {
let mut v = ~[];
vec::reserve(v, s.size());
do s.each_key() |k| {
@ -452,9 +432,9 @@ fn vec_from_set<T: copy>(s: set<T>) -> ~[T] {
}
/// Construct a hashmap from a vector
fn hash_from_vec<K: const copy, V: copy>(+hasher: hashfn<K>, +eqer: eqfn<K>,
items: &[(K, V)]) -> hashmap<K, V> {
let map = hashmap(hasher, eqer);
fn hash_from_vec<K: Eq IterBytes Hash const copy, V: copy>(
items: &[(K, V)]) -> hashmap<K, V> {
let map = hashmap();
do vec::iter(items) |item| {
let (key, value) = item;
map.insert(key, value);
@ -464,22 +444,22 @@ fn hash_from_vec<K: const copy, V: copy>(+hasher: hashfn<K>, +eqer: eqfn<K>,
/// Construct a hashmap from a vector with string keys
fn hash_from_strs<V: copy>(items: &[(~str, V)]) -> hashmap<~str, V> {
hash_from_vec(str::hash, str::eq, items)
hash_from_vec(items)
}
/// Construct a hashmap from a vector with byte keys
fn hash_from_bytes<V: copy>(items: &[(~[u8], V)]) -> hashmap<~[u8], V> {
hash_from_vec(vec::u8::hash, vec::u8::eq, items)
hash_from_vec(items)
}
/// Construct a hashmap from a vector with int keys
fn hash_from_ints<V: copy>(items: &[(int, V)]) -> hashmap<int, V> {
hash_from_vec(|x| { int::hash(*x) }, |x, y| { int::eq(*x, *y) }, items)
hash_from_vec(items)
}
/// Construct a hashmap from a vector with uint keys
fn hash_from_uints<V: copy>(items: &[(uint, V)]) -> hashmap<uint, V> {
hash_from_vec(|x| { uint::hash(*x) }, |x, y| { uint::eq(*x, *y) } , items)
hash_from_vec(items)
}
// XXX Transitional
@ -594,13 +574,9 @@ mod tests {
debug!("*** starting test_simple");
pure fn eq_uint(x: &uint, y: &uint) -> bool { *x == *y }
pure fn uint_id(x: &uint) -> uint { *x }
let hasher_uint: map::hashfn<uint> = uint_id;
let eqer_uint: map::eqfn<uint> = eq_uint;
let hasher_str: map::hashfn<~str> = str::hash;
let eqer_str: map::eqfn<~str> = str::eq;
debug!("uint -> uint");
let hm_uu: map::hashmap<uint, uint> =
map::hashmap::<uint, uint>(copy hasher_uint, copy eqer_uint);
map::hashmap::<uint, uint>();
assert (hm_uu.insert(10u, 12u));
assert (hm_uu.insert(11u, 13u));
assert (hm_uu.insert(12u, 14u));
@ -616,7 +592,7 @@ mod tests {
let twelve: ~str = ~"twelve";
debug!("str -> uint");
let hm_su: map::hashmap<~str, uint> =
map::hashmap::<~str, uint>(copy hasher_str, copy eqer_str);
map::hashmap::<~str, uint>();
assert (hm_su.insert(~"ten", 12u));
assert (hm_su.insert(eleven, 13u));
assert (hm_su.insert(~"twelve", 14u));
@ -630,7 +606,7 @@ mod tests {
assert (hm_su.get(~"twelve") == 12u);
debug!("uint -> str");
let hm_us: map::hashmap<uint, ~str> =
map::hashmap::<uint, ~str>(copy hasher_uint, copy eqer_uint);
map::hashmap::<uint, ~str>();
assert (hm_us.insert(10u, ~"twelve"));
assert (hm_us.insert(11u, ~"thirteen"));
assert (hm_us.insert(12u, ~"fourteen"));
@ -643,7 +619,7 @@ mod tests {
assert hm_us.get(12u) == ~"twelve";
debug!("str -> str");
let hm_ss: map::hashmap<~str, ~str> =
map::hashmap::<~str, ~str>(copy hasher_str, copy eqer_str);
map::hashmap::<~str, ~str>();
assert (hm_ss.insert(ten, ~"twelve"));
assert (hm_ss.insert(eleven, ~"thirteen"));
assert (hm_ss.insert(twelve, ~"fourteen"));
@ -668,10 +644,8 @@ mod tests {
pure fn eq_uint(x: &uint, y: &uint) -> bool { *x == *y }
pure fn uint_id(x: &uint) -> uint { *x }
debug!("uint -> uint");
let hasher_uint: map::hashfn<uint> = uint_id;
let eqer_uint: map::eqfn<uint> = eq_uint;
let hm_uu: map::hashmap<uint, uint> =
map::hashmap::<uint, uint>(hasher_uint, eqer_uint);
map::hashmap::<uint, uint>();
let mut i: uint = 0u;
while i < num_to_insert {
assert (hm_uu.insert(i, i * i));
@ -695,10 +669,8 @@ mod tests {
i += 1u;
}
debug!("str -> str");
let hasher_str: map::hashfn<~str> = str::hash;
let eqer_str: map::eqfn<~str> = str::eq;
let hm_ss: map::hashmap<~str, ~str> =
map::hashmap::<~str, ~str>(hasher_str, eqer_str);
map::hashmap::<~str, ~str>();
i = 0u;
while i < num_to_insert {
assert hm_ss.insert(uint::to_str(i, 2u), uint::to_str(i * i, 2u));
@ -745,10 +717,8 @@ mod tests {
assert (hash(&0u) == hash(&1u));
assert (hash(&2u) == hash(&3u));
assert (hash(&0u) != hash(&2u));
let hasher: map::hashfn<uint> = hash;
let eqer: map::eqfn<uint> = eq;
let hm: map::hashmap<uint, uint> =
map::hashmap::<uint, uint>(hasher, eqer);
map::hashmap::<uint, uint>();
let mut i: uint = 0u;
while i < num_to_insert {
assert (hm.insert(i, i * i));
@ -808,7 +778,7 @@ mod tests {
#[test]
fn test_contains_key() {
let key = ~"k";
let map = map::hashmap::<~str, ~str>(str::hash, str::eq);
let map = map::hashmap::<~str, ~str>();
assert (!map.contains_key(key));
map.insert(key, ~"val");
assert (map.contains_key(key));
@ -817,7 +787,7 @@ mod tests {
#[test]
fn test_find() {
let key = ~"k";
let map = map::hashmap::<~str, ~str>(str::hash, str::eq);
let map = map::hashmap::<~str, ~str>();
assert (option::is_none(map.find(key)));
map.insert(key, ~"val");
assert (option::get(map.find(key)) == ~"val");
@ -826,7 +796,7 @@ mod tests {
#[test]
fn test_clear() {
let key = ~"k";
let map = map::hashmap::<~str, ~str>(str::hash, str::eq);
let map = map::hashmap::<~str, ~str>();
map.insert(key, ~"val");
assert (map.size() == 1);
assert (map.contains_key(key));

View File

@ -310,6 +310,22 @@ enum binding_mode {
bind_by_implicit_ref
}
impl binding_mode : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
bind_by_value => 0u8.iter_bytes(lsb0, f),
bind_by_move => 1u8.iter_bytes(lsb0, f),
bind_by_ref(ref m) =>
to_bytes::iter_bytes_2(&2u8, m, lsb0, f),
bind_by_implicit_ref =>
3u8.iter_bytes(lsb0, f),
}
}
}
impl binding_mode : cmp::Eq {
pure fn eq(&&other: binding_mode) -> bool {
match self {
@ -368,6 +384,12 @@ enum pat_ {
#[auto_serialize]
enum mutability { m_mutbl, m_imm, m_const, }
impl mutability : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl mutability: cmp::Eq {
pure fn eq(&&other: mutability) -> bool {
(self as uint) == (other as uint)
@ -443,6 +465,18 @@ enum inferable<T> {
infer(node_id)
}
impl<T: to_bytes::IterBytes> inferable<T> : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
expl(ref t) =>
to_bytes::iter_bytes_2(&0u8, t, lsb0, f),
infer(ref n) =>
to_bytes::iter_bytes_2(&1u8, n, lsb0, f),
}
}
}
impl<T:cmp::Eq> inferable<T> : cmp::Eq {
pure fn eq(&&other: inferable<T>) -> bool {
match self {
@ -467,6 +501,13 @@ impl<T:cmp::Eq> inferable<T> : cmp::Eq {
#[auto_serialize]
enum rmode { by_ref, by_val, by_mutbl_ref, by_move, by_copy }
impl rmode : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl rmode : cmp::Eq {
pure fn eq(&&other: rmode) -> bool {
(self as uint) == (other as uint)
@ -822,6 +863,12 @@ enum trait_method {
#[auto_serialize]
enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
impl int_ty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl int_ty: cmp::Eq {
pure fn eq(&&other: int_ty) -> bool {
match (self, other) {
@ -845,6 +892,12 @@ impl int_ty: cmp::Eq {
#[auto_serialize]
enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
impl uint_ty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl uint_ty: cmp::Eq {
pure fn eq(&&other: uint_ty) -> bool {
match (self, other) {
@ -866,6 +919,11 @@ impl uint_ty: cmp::Eq {
#[auto_serialize]
enum float_ty { ty_f, ty_f32, ty_f64, }
impl float_ty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl float_ty: cmp::Eq {
pure fn eq(&&other: float_ty) -> bool {
match (self, other) {
@ -954,6 +1012,24 @@ enum ty_ {
ty_infer,
}
// Equality and byte-iter (hashing) can be quite approximate for AST types.
// since we only care about this for normalizing them to "real" types.
impl ty : cmp::Eq {
pure fn eq(&&other: ty) -> bool {
ptr::addr_of(self) == ptr::addr_of(other)
}
pure fn ne(&&other: ty) -> bool {
ptr::addr_of(self) != ptr::addr_of(other)
}
}
impl ty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f);
}
}
#[auto_serialize]
type arg = {mode: mode, ty: @ty, ident: ident, id: node_id};
@ -971,6 +1047,12 @@ enum purity {
extern_fn, // declared with "extern fn"
}
impl purity : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl purity : cmp::Eq {
pure fn eq(&&other: purity) -> bool {
(self as uint) == (other as uint)
@ -985,6 +1067,12 @@ enum ret_style {
return_val, // everything else
}
impl ret_style : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl ret_style : cmp::Eq {
pure fn eq(&&other: ret_style) -> bool {
match (self, other) {
@ -1276,6 +1364,12 @@ enum item_ {
#[auto_serialize]
enum class_mutability { class_mutable, class_immutable }
impl class_mutability : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl class_mutability : cmp::Eq {
pure fn eq(&&other: class_mutability) -> bool {
match (self, other) {

View File

@ -251,28 +251,16 @@ pure fn is_call_expr(e: @expr) -> bool {
match e.node { expr_call(_, _, _) => true, _ => false }
}
pure fn eq_ty(a: &@ty, b: &@ty) -> bool { box::ptr_eq(*a, *b) }
pure fn hash_ty(t: &@ty) -> uint {
let res = (t.span.lo << 16u) + t.span.hi;
return res;
}
pure fn def_eq(a: &ast::def_id, b: &ast::def_id) -> bool {
a.crate == b.crate && a.node == b.node
}
pure fn hash_def(d: &ast::def_id) -> uint {
let mut h = 5381u;
h = (h << 5u) + h ^ (d.crate as uint);
h = (h << 5u) + h ^ (d.node as uint);
return h;
// This makes def_id hashable
impl def_id : core::to_bytes::IterBytes {
#[inline(always)]
fn iter_bytes(lsb0: bool, f: core::to_bytes::Cb) {
core::to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f);
}
}
fn new_def_hash<V: copy>() -> std::map::hashmap<ast::def_id, V> {
let hasher: std::map::hashfn<ast::def_id> = hash_def;
let eqer: std::map::eqfn<ast::def_id> = def_eq;
return std::map::hashmap::<ast::def_id, V>(hasher, eqer);
return std::map::hashmap::<ast::def_id, V>();
}
fn block_from_expr(e: @expr) -> blk {

View File

@ -345,8 +345,7 @@ fn mk_ident_interner() -> ident_interner {
@~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static",
@~"intrinsic", @~"__foreign_mod__"];
let rv = interner::mk_prefill::<@~str>(|x| str::hash(*x),
|x,y| str::eq(*x, *y), init_vec);
let rv = interner::mk_prefill::<@~str>(init_vec);
/* having multiple interners will just confuse the serializer */
unsafe{ assert task::local_data_get(interner_key!()).is_none() };
@ -357,7 +356,7 @@ fn mk_ident_interner() -> ident_interner {
/* for when we don't care about the contents; doesn't interact with TLD or
serialization */
fn mk_fake_ident_interner() -> ident_interner {
interner::mk::<@~str>(|x| str::hash(*x), |x,y| str::eq(*x, *y))
interner::mk::<@~str>()
}
/**

View File

@ -2,40 +2,39 @@
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.
use std::map;
use std::map::{hashmap, hashfn, eqfn};
use std::map::hashmap;
use dvec::DVec;
use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;
type hash_interner<T: const> =
{map: hashmap<T, uint>,
vect: DVec<T>,
hasher: hashfn<T>,
eqer: eqfn<T>};
vect: DVec<T>};
fn mk<T: const copy>(+hasher: hashfn<T>, +eqer: eqfn<T>) -> interner<T> {
let m = map::hashmap::<T, uint>(copy hasher, copy eqer);
fn mk<T:Eq IterBytes Hash const copy>() -> interner<T> {
let m = map::hashmap::<T, uint>();
let hi: hash_interner<T> =
{map: m, vect: DVec(), hasher: hasher, eqer: eqer};
{map: m, vect: DVec()};
return hi as interner::<T>;
}
fn mk_prefill<T: const copy>(hasher: hashfn<T>, eqer: eqfn<T>,
init: ~[T]) -> interner<T> {
let rv = mk(copy hasher, copy eqer);
fn mk_prefill<T:Eq IterBytes Hash const copy>(init: ~[T]) -> interner<T> {
let rv = mk();
for init.each() |v| { rv.intern(v); }
return rv;
}
/* when traits can extend traits, we should extend index<uint,T> to get [] */
trait interner<T: const copy> {
trait interner<T:Eq IterBytes Hash const copy> {
fn intern(T) -> uint;
fn gensym(T) -> uint;
pure fn get(uint) -> T;
fn len() -> uint;
}
impl <T: const copy> hash_interner<T>: interner<T> {
impl <T:Eq IterBytes Hash const copy> hash_interner<T>: interner<T> {
fn intern(val: T) -> uint {
match self.map.find(val) {
Some(idx) => return idx,

View File

@ -1057,7 +1057,7 @@ fn name_has_type(tn: type_names, s: ~str) -> Option<TypeRef> {
fn mk_type_names() -> type_names {
pure fn hash(t: &TypeRef) -> uint { *t as uint }
pure fn eq(a: &TypeRef, b: &TypeRef) -> bool { *a == *b }
@{type_names: std::map::hashmap(hash, eq),
@{type_names: std::map::hashmap(),
named_types: std::map::str_hash()}
}

View File

@ -404,8 +404,24 @@ fn save_and_restore<T:copy,U>(&save_and_restore_t: T, f: fn() -> U) -> U {
}
/// Creates and returns a new root_map
impl root_map_key : cmp::Eq {
pure fn eq(&&other: root_map_key) -> bool {
self.id == other.id && self.derefs == other.derefs
}
pure fn ne(&&other: root_map_key) -> bool {
! (self == other)
}
}
impl root_map_key : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.id, &self.derefs, lsb0, f);
}
}
fn root_map() -> root_map {
return hashmap(root_map_key_hash, root_map_key_eq);
return hashmap();
pure fn root_map_key_eq(k1: &root_map_key, k2: &root_map_key) -> bool {
k1.id == k2.id && k1.derefs == k2.derefs

View File

@ -309,7 +309,7 @@ fn Atom(n: uint) -> Atom {
/// Creates a hash table of atoms.
fn atom_hashmap<V:copy>() -> hashmap<Atom,V> {
hashmap::<Atom,V>(|x| { uint::hash(*x) }, |x, y| { uint::eq(*x, *y) })
hashmap::<Atom,V>()
}
/// One local scope.

View File

@ -2658,10 +2658,10 @@ fn trans_crate(sess: session::session,
tydescs: ty::new_ty_hash(),
mut finished_tydescs: false,
external: ast_util::new_def_hash(),
monomorphized: map::hashmap(hash_mono_id, sys::shape_eq),
monomorphized: map::hashmap(),
monomorphizing: ast_util::new_def_hash(),
type_use_cache: ast_util::new_def_hash(),
vtables: map::hashmap(hash_mono_id, sys::shape_eq),
vtables: map::hashmap(),
const_cstr_cache: map::str_hash(),
const_globals: int_hash::<ValueRef>(),
module_data: str_hash::<ValueRef>(),

View File

@ -1125,24 +1125,24 @@ impl mono_id_: cmp::Eq {
pure fn ne(&&other: mono_id_) -> bool { !self.eq(other) }
}
pure fn hash_mono_id(mi: &mono_id) -> uint {
let mut h = syntax::ast_util::hash_def(&mi.def);
for vec::each(mi.params) |param| {
h = h * match param {
mono_precise(ty, vts) => {
let mut h = ty::type_id(ty);
do option::iter(vts) |vts| {
for vec::each(vts) |vt| {
h += hash_mono_id(&vt);
}
}
h
}
mono_any => 1u,
mono_repr(sz, align) => sz * (align + 2u)
impl mono_param_id : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
mono_precise(t, mids) =>
to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), &mids, lsb0, f),
mono_any => 1u8.iter_bytes(lsb0, f),
mono_repr(a,b) =>
to_bytes::iter_bytes_3(&2u8, &a, &b, lsb0, f)
}
}
h
}
impl mono_id_ : core::to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f);
}
}
fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {

View File

@ -22,8 +22,34 @@ use option::is_some;
use ty_ctxt = middle::ty::ctxt;
type nominal_id = @{did: ast::def_id, parent_id: Option<ast::def_id>,
type nominal_id_ = {did: ast::def_id, parent_id: Option<ast::def_id>,
tps: ~[ty::t]};
type nominal_id = @nominal_id_;
impl nominal_id_ : core::cmp::Eq {
pure fn eq(&&other: nominal_id_) -> bool {
if self.did != other.did ||
self.parent_id != other.parent_id {
false
} else {
do vec::all2(self.tps, other.tps) |m_tp, n_tp| {
ty::type_id(m_tp) == ty::type_id(n_tp)
}
}
}
pure fn ne(&&other: nominal_id_) -> bool {
! (self == other)
}
}
impl nominal_id_ : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.did, &self.parent_id, lsb0, f);
for self.tps.each |t| {
ty::type_id(t).iter_bytes(lsb0, f);
}
}
}
fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id,
parent_id: Option<ast::def_id>,
@ -32,31 +58,8 @@ fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id,
@{did: did, parent_id: parent_id, tps: tps_norm}
}
pure fn hash_nominal_id(ri: &nominal_id) -> uint {
let mut h = 5381u;
h *= 33u;
h += ri.did.crate as uint;
h *= 33u;
h += ri.did.node as uint;
for vec::each(ri.tps) |t| {
h *= 33u;
h += ty::type_id(t);
}
return h;
}
pure fn eq_nominal_id(mi: &nominal_id, ni: &nominal_id) -> bool {
if mi.did != ni.did {
false
} else {
do vec::all2(mi.tps, ni.tps) |m_tp, n_tp| {
ty::type_id(m_tp) == ty::type_id(n_tp)
}
}
}
fn new_nominal_id_hash<T: copy>() -> hashmap<nominal_id, T> {
return hashmap(hash_nominal_id, eq_nominal_id);
return hashmap();
}
type enum_data = {did: ast::def_id, substs: ty::substs};
@ -193,7 +196,7 @@ fn mk_ctxt(llmod: ModuleRef) -> ctxt {
pad: 0u16,
tag_id_to_index: new_nominal_id_hash(),
tag_order: DVec(),
resources: interner::mk(hash_nominal_id, eq_nominal_id),
resources: interner::mk(),
llshapetablesty: llshapetablesty,
llshapetables: llshapetables};
}

View File

@ -226,7 +226,25 @@ type field_ty = {
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
type creader_cache = hashmap<{cnum: int, pos: uint, len: uint}, t>;
type creader_cache_key = {cnum: int, pos: uint, len: uint};
type creader_cache = hashmap<creader_cache_key, t>;
impl creader_cache_key : cmp::Eq {
pure fn eq(&&other: creader_cache_key) -> bool {
self.cnum == other.cnum &&
self.pos == other.pos &&
self.len == other.len
}
pure fn ne(&&other: creader_cache_key) -> bool {
!(self == other)
}
}
impl creader_cache_key : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f);
}
}
type intern_key = {struct: sty, o_def_id: Option<ast::def_id>};
@ -237,6 +255,12 @@ impl intern_key: cmp::Eq {
pure fn ne(&&other: intern_key) -> bool { !self.eq(other) }
}
impl intern_key : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.struct, &self.o_def_id, lsb0, f);
}
}
enum ast_ty_to_ty_cache_entry {
atttce_unresolved, /* not resolved yet */
atttce_resolved(t) /* resolved to a type, irrespective of region */
@ -366,6 +390,12 @@ enum closure_kind {
ck_uniq,
}
impl closure_kind : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(self as u8).iter_bytes(lsb0, f)
}
}
impl closure_kind : cmp::Eq {
pure fn eq(&&other: closure_kind) -> bool {
(self as uint) == (other as uint)
@ -378,6 +408,18 @@ enum fn_proto {
proto_vstore(vstore)
}
impl fn_proto : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
proto_bare =>
0u8.iter_bytes(lsb0, f),
proto_vstore(ref v) =>
to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
}
}
}
impl fn_proto : cmp::Eq {
pure fn eq(&&other: fn_proto) -> bool {
match self {
@ -444,6 +486,13 @@ impl param_ty: cmp::Eq {
pure fn ne(&&other: param_ty) -> bool { !self.eq(other) }
}
impl param_ty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.idx, &self.def_id, lsb0, f)
}
}
/// Representation of regions:
enum region {
/// Bound regions are found (primarily) in function types. They indicate
@ -606,6 +655,28 @@ enum InferTy {
IntVar(IntVid)
}
impl InferTy : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f)
}
}
}
impl param_bound : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
bound_copy => 0u8.iter_bytes(lsb0, f),
bound_owned => 1u8.iter_bytes(lsb0, f),
bound_send => 2u8.iter_bytes(lsb0, f),
bound_const => 3u8.iter_bytes(lsb0, f),
bound_trait(ref t) =>
to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
}
}
}
trait vid {
pure fn to_uint() -> uint;
pure fn to_str() -> ~str;
@ -657,6 +728,30 @@ impl purity: purity_to_str {
}
}
impl RegionVid : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
}
}
impl TyVid : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
}
}
impl IntVid : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
}
}
impl FnVid : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
(*self).iter_bytes(lsb0, f)
}
}
fn param_bounds_to_kind(bounds: param_bounds) -> kind {
let mut kind = kind_noncopyable();
for vec::each(*bounds) |bound| {
@ -701,18 +796,11 @@ type node_type_table = @smallintmap::SmallIntMap<t>;
fn mk_rcache() -> creader_cache {
type val = {cnum: int, pos: uint, len: uint};
pure fn hash_cache_entry(k: &val) -> uint {
(k.cnum as uint) + k.pos + k.len
}
pure fn eq_cache_entries(a: &val, b: &val) -> bool {
a.cnum == b.cnum && a.pos == b.pos && a.len == b.len
}
return map::hashmap(hash_cache_entry, eq_cache_entries);
return map::hashmap();
}
fn new_ty_hash<V: copy>() -> map::hashmap<t, V> {
map::hashmap(|t: &t| type_id(*t),
|a: &t, b: &t| type_id(*a) == type_id(*b))
map::hashmap()
}
fn mk_ctxt(s: session::session,
@ -721,11 +809,7 @@ fn mk_ctxt(s: session::session,
freevars: freevars::freevar_map,
region_map: middle::region::region_map,
region_paramd_items: middle::region::region_paramd_items) -> ctxt {
pure fn hash_intern_key(k: &intern_key) -> uint {
hash_type_structure(&k.struct) +
option::map_default(k.o_def_id, 0u, |d| ast_util::hash_def(&d))
}
let interner = map::hashmap(hash_intern_key, sys::shape_eq);
let interner = map::hashmap();
let vecs_implicitly_copyable =
get_lint_level(s.lint_settings.default_settings,
lint::vecs_implicitly_copyable) == allow;
@ -750,8 +834,7 @@ fn mk_ctxt(s: session::session,
needs_drop_cache: new_ty_hash(),
needs_unwind_cleanup_cache: new_ty_hash(),
kind_cache: new_ty_hash(),
ast_ty_to_ty_cache: map::hashmap(
ast_util::hash_ty, ast_util::eq_ty),
ast_ty_to_ty_cache: map::hashmap(),
enum_var_cache: new_def_hash(),
trait_method_cache: new_def_hash(),
ty_param_bounds: map::int_hash(),
@ -2314,6 +2397,167 @@ fn index_sty(cx: ctxt, sty: &sty) -> Option<mt> {
}
}
impl bound_region : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
ty::br_self => 0u8.iter_bytes(lsb0, f),
ty::br_anon(ref idx) =>
to_bytes::iter_bytes_2(&1u8, idx, lsb0, f),
ty::br_named(ref ident) =>
to_bytes::iter_bytes_2(&2u8, ident, lsb0, f),
ty::br_cap_avoid(ref id, ref br) =>
to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f)
}
}
}
impl region : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
re_bound(ref br) =>
to_bytes::iter_bytes_2(&0u8, br, lsb0, f),
re_free(ref id, ref br) =>
to_bytes::iter_bytes_3(&1u8, id, br, lsb0, f),
re_scope(ref id) =>
to_bytes::iter_bytes_2(&2u8, id, lsb0, f),
re_var(ref id) =>
to_bytes::iter_bytes_2(&3u8, id, lsb0, f),
re_static => 4u8.iter_bytes(lsb0, f)
}
}
}
impl vstore : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
vstore_fixed(ref u) =>
to_bytes::iter_bytes_2(&0u8, u, lsb0, f),
vstore_uniq => 1u8.iter_bytes(lsb0, f),
vstore_box => 2u8.iter_bytes(lsb0, f),
vstore_slice(ref r) =>
to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
}
}
}
impl substs : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_3(&self.self_r,
&self.self_ty,
&self.tps, lsb0, f)
}
}
impl mt : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.ty,
&self.mutbl, lsb0, f)
}
}
impl field : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.ident,
&self.mt, lsb0, f)
}
}
impl arg : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.mode,
&self.ty, lsb0, f)
}
}
impl sty : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
ty_nil => 0u8.iter_bytes(lsb0, f),
ty_bool => 1u8.iter_bytes(lsb0, f),
ty_int(ref t) =>
to_bytes::iter_bytes_2(&2u8, t, lsb0, f),
ty_uint(ref t) =>
to_bytes::iter_bytes_2(&3u8, t, lsb0, f),
ty_float(ref t) =>
to_bytes::iter_bytes_2(&4u8, t, lsb0, f),
ty_estr(ref v) =>
to_bytes::iter_bytes_2(&5u8, v, lsb0, f),
ty_enum(ref did, ref substs) =>
to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f),
ty_box(ref mt) =>
to_bytes::iter_bytes_2(&7u8, mt, lsb0, f),
ty_evec(ref mt, ref v) =>
to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),
ty_unboxed_vec(ref mt) =>
to_bytes::iter_bytes_2(&9u8, mt, lsb0, f),
ty_tup(ref ts) =>
to_bytes::iter_bytes_2(&10u8, ts, lsb0, f),
ty_rec(ref fs) =>
to_bytes::iter_bytes_2(&11u8, fs, lsb0, f),
ty_fn(ref ft) =>
to_bytes::iter_bytes_7(&12u8,
&ft.meta.purity,
&ft.meta.proto,
&ft.meta.bounds,
&ft.sig.inputs,
&ft.sig.output,
&ft.meta.ret_style,
lsb0, f),
ty_self => 13u8.iter_bytes(lsb0, f),
ty_infer(ref v) =>
to_bytes::iter_bytes_2(&14u8, v, lsb0, f),
ty_param(ref p) =>
to_bytes::iter_bytes_2(&15u8, p, lsb0, f),
ty_type => 16u8.iter_bytes(lsb0, f),
ty_bot => 17u8.iter_bytes(lsb0, f),
ty_ptr(ref mt) =>
to_bytes::iter_bytes_2(&18u8, mt, lsb0, f),
ty_uniq(ref mt) =>
to_bytes::iter_bytes_2(&19u8, mt, lsb0, f),
ty_trait(ref did, ref substs, ref v) =>
to_bytes::iter_bytes_4(&20u8, did, substs, v, lsb0, f),
ty_opaque_closure_ptr(ref ck) =>
to_bytes::iter_bytes_2(&21u8, ck, lsb0, f),
ty_opaque_box => 22u8.iter_bytes(lsb0, f),
ty_class(ref did, ref substs) =>
to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),
ty_rptr(ref r, ref mt) =>
to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
}
}
}
pure fn hash_bound_region(br: &bound_region) -> uint {
match *br { // no idea if this is any good
ty::br_self => 0u,
@ -2325,7 +2569,7 @@ pure fn hash_bound_region(br: &bound_region) -> uint {
}
fn br_hashmap<V:copy>() -> hashmap<bound_region, V> {
map::hashmap(hash_bound_region, sys::shape_eq)
map::hashmap()
}
pure fn hash_region(r: &region) -> uint {
@ -3328,7 +3572,7 @@ fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
let mut i = 0u;
while i < vec::len::<variant_info>(*variants) {
let variant = variants[i];
if ast_util::def_eq(&variant.id, &variant_id) { return variant; }
if variant.id == variant_id { return variant; }
i += 1u;
}
cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");

View File

@ -349,6 +349,21 @@ impl Constraint: cmp::Eq {
pure fn ne(&&other: Constraint) -> bool { !self.eq(other) }
}
impl Constraint : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
match self {
ConstrainVarSubVar(ref v0, ref v1) =>
to_bytes::iter_bytes_3(&0u8, v0, v1, lsb0, f),
ConstrainRegSubVar(ref ra, ref va) =>
to_bytes::iter_bytes_3(&1u8, ra, va, lsb0, f),
ConstrainVarSubReg(ref va, ref ra) =>
to_bytes::iter_bytes_3(&2u8, va, ra, lsb0, f)
}
}
}
struct TwoRegions {
a: region,
b: region,
@ -361,6 +376,12 @@ impl TwoRegions: cmp::Eq {
pure fn ne(&&other: TwoRegions) -> bool { !self.eq(other) }
}
impl TwoRegions : to_bytes::IterBytes {
fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.a, &self.b, lsb0, f)
}
}
enum UndoLogEntry {
Snapshot,
AddVar(RegionVid),
@ -394,7 +415,7 @@ fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings {
tcx: tcx,
var_spans: DVec(),
values: empty_cell(),
constraints: hashmap(hash_constraint, sys::shape_eq),
constraints: hashmap(),
lubs: CombineMap(),
glbs: CombineMap(),
undo_log: DVec()
@ -405,16 +426,7 @@ fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings {
// `b`! Not obvious that this is the most efficient way to go about
// it.
fn CombineMap() -> CombineMap {
return hashmap(hash_two_regions, eq_two_regions);
pure fn hash_two_regions(rc: &TwoRegions) -> uint {
hash_region(&rc.a) ^ hash_region(&rc.b)
}
pure fn eq_two_regions(rc1: &TwoRegions, rc2: &TwoRegions) -> bool {
(rc1.a == rc2.a && rc1.b == rc2.b) ||
(rc1.a == rc2.b && rc1.b == rc2.a)
}
return hashmap();
}
pure fn hash_constraint(rc: &Constraint) -> uint {
@ -795,11 +807,7 @@ struct SpannedRegion {
type TwoRegionsMap = hashmap<TwoRegions, ()>;
fn TwoRegionsMap() -> TwoRegionsMap {
return hashmap(hash_two_regions, sys::shape_eq);
pure fn hash_two_regions(rc: &TwoRegions) -> uint {
hash_region(&rc.a) ^ (hash_region(&rc.b) << 2)
}
return hashmap();
}
impl RegionVarBindings {

View File

@ -5,8 +5,7 @@ use std::map;
fn main() {
let buggy_map :hashmap<uint, &uint> =
hashmap::<uint, &uint>(|x| { uint::hash(*x) },
|x, y| { uint::eq(*x, *y) });
hashmap::<uint, &uint>();
buggy_map.insert(42, ~1); //~ ERROR illegal borrow
// but it is ok if we use a temporary

View File

@ -1,7 +1,6 @@
mod argparse {
use std;
import std::map;
import either::{Either, Left, Right};
struct Flag {

View File

@ -6,19 +6,13 @@ use std::map::hashmap;
fn main() {
let count = @mut 0u;
pure fn hash(s: &~[@~str]) -> uint {
if vec::len(*s) > 0u && *s[0] == ~"boom" { fail; }
return 10u;
}
pure fn eq(s: &~[@~str], t: &~[@~str]) -> bool {
return *s == *t;
}
let map = map::hashmap(hash, eq);
let map = map::hashmap();
let mut arr = ~[];
for uint::range(0u, 10u) |i| {
arr += ~[@~"key stuff"];
map.insert(arr, arr + ~[@~"value stuff"]);
if arr.len() == 5 {
fail;
}
}
map.insert(~[@~"boom"], ~[]);
}