Skip to content

Commit 1384a43

Browse files
author
Jorge Aparicio
committed
DSTify Hash
- The signature of the `*_equiv` methods of `HashMap` and similar structures have changed, and now require one less level of indirection. Change your code from: ``` hashmap.find_equiv(&"Hello"); hashmap.find_equiv(&&[0u8, 1, 2]); ``` to: ``` hashmap.find_equiv("Hello"); hashmap.find_equiv(&[0u8, 1, 2]); ``` - The generic parameter `T` of the `Hasher::hash<T>` method have become `Sized?`. Downstream code must add `Sized?` to that method in their implementations. For example: ``` impl Hasher<FnvState> for FnvHasher { fn hash<T: Hash<FnvState>>(&self, t: &T) -> u64 { /* .. */ } } ``` must be changed to: ``` impl Hasher<FnvState> for FnvHasher { fn hash<Sized? T: Hash<FnvState>>(&self, t: &T) -> u64 { /* .. */ } // ^^^^^^ } ``` [breaking-change]
1 parent 065caf3 commit 1384a43

File tree

26 files changed

+83
-74
lines changed

26 files changed

+83
-74
lines changed

src/libcollections/hash/mod.rs

+21-16
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub mod sip;
8080
/// A hashable type. The `S` type parameter is an abstract hash state that is
8181
/// used by the `Hash` to compute the hash. It defaults to
8282
/// `std::hash::sip::SipState`.
83-
pub trait Hash<S = sip::SipState> {
83+
pub trait Hash<S = sip::SipState> for Sized? {
8484
/// Computes the hash of a value.
8585
fn hash(&self, state: &mut S);
8686
}
@@ -89,7 +89,7 @@ pub trait Hash<S = sip::SipState> {
8989
/// containers like `HashMap`, which need a generic way hash multiple types.
9090
pub trait Hasher<S> {
9191
/// Compute the hash of a value.
92-
fn hash<T: Hash<S>>(&self, value: &T) -> u64;
92+
fn hash<Sized? T: Hash<S>>(&self, value: &T) -> u64;
9393
}
9494

9595
pub trait Writer {
@@ -137,7 +137,7 @@ impl<S: Writer> Hash<S> for char {
137137
}
138138
}
139139

140-
impl<'a, S: Writer> Hash<S> for &'a str {
140+
impl<S: Writer> Hash<S> for str {
141141
#[inline]
142142
fn hash(&self, state: &mut S) {
143143
state.write(self.as_bytes());
@@ -186,7 +186,7 @@ impl_hash_tuple!(A B C D E F G H I J)
186186
impl_hash_tuple!(A B C D E F G H I J K)
187187
impl_hash_tuple!(A B C D E F G H I J K L)
188188

189-
impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
189+
impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
190190
#[inline]
191191
fn hash(&self, state: &mut S) {
192192
self.len().hash(state);
@@ -197,41 +197,35 @@ impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
197197
}
198198

199199

200-
impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
201-
#[inline]
202-
fn hash(&self, state: &mut S) {
203-
self.as_slice().hash(state);
204-
}
205-
}
206-
207200
impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
208201
#[inline]
209202
fn hash(&self, state: &mut S) {
210203
self.as_slice().hash(state);
211204
}
212205
}
213206

214-
impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
207+
impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a T {
215208
#[inline]
216209
fn hash(&self, state: &mut S) {
217210
(**self).hash(state);
218211
}
219212
}
220213

221-
impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
214+
impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a mut T {
222215
#[inline]
223216
fn hash(&self, state: &mut S) {
224217
(**self).hash(state);
225218
}
226219
}
227220

228-
impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
221+
impl<S: Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
229222
#[inline]
230223
fn hash(&self, state: &mut S) {
231224
(**self).hash(state);
232225
}
233226
}
234227

228+
// FIXME (#18248) Make `T` `Sized?`
235229
impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
236230
#[inline]
237231
fn hash(&self, state: &mut S) {
@@ -293,6 +287,7 @@ impl<S: Writer, T: Hash<S>, U: Hash<S>> Hash<S> for Result<T, U> {
293287

294288
#[cfg(test)]
295289
mod tests {
290+
use core::kinds::Sized;
296291
use std::mem;
297292

298293
use slice::ImmutableSlice;
@@ -301,7 +296,7 @@ mod tests {
301296
struct MyWriterHasher;
302297

303298
impl Hasher<MyWriter> for MyWriterHasher {
304-
fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
299+
fn hash<Sized? T: Hash<MyWriter>>(&self, value: &T) -> u64 {
305300
let mut state = MyWriter { hash: 0 };
306301
value.hash(&mut state);
307302
state.hash
@@ -323,6 +318,8 @@ mod tests {
323318

324319
#[test]
325320
fn test_writer_hasher() {
321+
use alloc::boxed::Box;
322+
326323
let hasher = MyWriterHasher;
327324

328325
assert_eq!(hasher.hash(&()), 0);
@@ -344,9 +341,17 @@ mod tests {
344341

345342
assert_eq!(hasher.hash(&'a'), 97);
346343

347-
assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
344+
let s: &str = "a";
345+
assert_eq!(hasher.hash(& s), 97 + 0xFF);
346+
// FIXME (#18283) Enable test
347+
//let s: Box<str> = box "a";
348+
//assert_eq!(hasher.hash(& s), 97 + 0xFF);
348349
let cs: &[u8] = &[1u8, 2u8, 3u8];
349350
assert_eq!(hasher.hash(& cs), 9);
351+
let cs: Box<[u8]> = box [1u8, 2u8, 3u8];
352+
assert_eq!(hasher.hash(& cs), 9);
353+
354+
// FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
350355

351356
unsafe {
352357
let ptr: *const int = mem::transmute(5i);

src/libcollections/hash/sip.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ impl SipHasher {
235235

236236
impl Hasher<SipState> for SipHasher {
237237
#[inline]
238-
fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
238+
fn hash<Sized? T: Hash<SipState>>(&self, value: &T) -> u64 {
239239
let mut state = SipState::new_with_keys(self.k0, self.k1);
240240
value.hash(&mut state);
241241
state.result()

src/libcore/cmp.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
4040
#![stable]
4141

42+
use kinds::Sized;
4243
use option::{Option, Some, None};
4344

4445
/// Trait for values that can be compared for equality and inequality.
@@ -236,7 +237,7 @@ pub trait PartialOrd: PartialEq {
236237
/// container types; e.g. it is often desirable to be able to use `&str`
237238
/// values to look up entries in a container with `String` keys.
238239
#[experimental = "Better solutions may be discovered."]
239-
pub trait Equiv<T> {
240+
pub trait Equiv<T> for Sized? {
240241
/// Implement this function to decide equivalent values.
241242
fn equiv(&self, other: &T) -> bool;
242243
}

src/libcore/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ impl<'a,T:PartialEq> PartialEq for &'a [T] {
15651565
impl<'a,T:Eq> Eq for &'a [T] {}
15661566

15671567
#[unstable = "waiting for DST"]
1568-
impl<'a,T:PartialEq, V: AsSlice<T>> Equiv<V> for &'a [T] {
1568+
impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for [T] {
15691569
#[inline]
15701570
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
15711571
}

src/libcore/str.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1160,9 +1160,9 @@ pub mod traits {
11601160
}
11611161
}
11621162

1163-
impl<'a, S: Str> Equiv<S> for &'a str {
1163+
impl<S: Str> Equiv<S> for str {
11641164
#[inline]
1165-
fn equiv(&self, other: &S) -> bool { eq_slice(*self, other.as_slice()) }
1165+
fn equiv(&self, other: &S) -> bool { eq_slice(self, other.as_slice()) }
11661166
}
11671167

11681168
impl ops::Slice<uint, str> for str {

src/libregex/re.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ impl<'t> Captures<'t> {
724724
match self.named {
725725
None => "",
726726
Some(ref h) => {
727-
match h.find_equiv(&name) {
727+
match h.find_equiv(name) {
728728
None => "",
729729
Some(i) => self.at(*i),
730730
}

src/librustc/lint/context.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl LintStore {
164164
}
165165

166166
fn register_renamed(&mut self, old_name: &str, new_name: &str) {
167-
let target = match self.by_name.find_equiv(&new_name) {
167+
let target = match self.by_name.find_equiv(new_name) {
168168
Some(&Id(lint_id)) => lint_id.clone(),
169169
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
170170
};
@@ -258,7 +258,7 @@ impl LintStore {
258258
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
259259
-> Option<LintId>
260260
{
261-
match self.by_name.find_equiv(&lint_name) {
261+
match self.by_name.find_equiv(lint_name) {
262262
Some(&Id(lint_id)) => Some(lint_id),
263263
Some(&Renamed(ref new_name, lint_id)) => {
264264
let warning = format!("lint {} has been renamed to {}",
@@ -280,7 +280,7 @@ impl LintStore {
280280
None => {
281281
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
282282
.collect::<HashMap<&'static str, Vec<LintId>>>()
283-
.find_equiv(&lint_name.as_slice()) {
283+
.find_equiv(lint_name.as_slice()) {
284284
Some(v) => {
285285
v.iter()
286286
.map(|lint_id: &LintId|
@@ -487,7 +487,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
487487
match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
488488
Some(lint_id) => vec![(lint_id, level, span)],
489489
None => {
490-
match self.lints.lint_groups.find_equiv(&lint_name.get()) {
490+
match self.lints.lint_groups.find_equiv(lint_name.get()) {
491491
Some(&(ref v, _)) => v.iter()
492492
.map(|lint_id: &LintId|
493493
(*lint_id, level, span))

src/librustc/metadata/creader.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ fn existing_match(e: &Env, name: &str,
303303
// `source` stores paths which are normalized which may be different
304304
// from the strings on the command line.
305305
let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
306-
match e.sess.opts.externs.find_equiv(&name) {
306+
match e.sess.opts.externs.find_equiv(name) {
307307
Some(locs) => {
308308
let found = locs.iter().any(|l| {
309309
let l = fs::realpath(&Path::new(l.as_slice())).ok();

src/librustc/metadata/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
295295
fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
296296
let name = reader::get_doc(item, tag_paths_data_name);
297297
let string = name.as_str_slice();
298-
match intr.find_equiv(&string) {
298+
match intr.find_equiv(string) {
299299
None => token::intern(string),
300300
Some(val) => val,
301301
}

src/librustc/metadata/filesearch.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'a> FileSearch<'a> {
5252
debug!("filesearch: searching lib path");
5353
let tlib_path = make_target_lib_path(self.sysroot,
5454
self.triple);
55-
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
55+
if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
5656
match f(&tlib_path) {
5757
FileMatches => found = true,
5858
FileDoesntMatch => ()
@@ -69,7 +69,7 @@ impl<'a> FileSearch<'a> {
6969
debug!("is {} in visited_dirs? {}", tlib_path.display(),
7070
visited_dirs.contains_equiv(&tlib_path.as_vec().to_vec()));
7171

72-
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
72+
if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
7373
visited_dirs.insert(tlib_path.as_vec().to_vec());
7474
// Don't keep searching the RUST_PATH if one match turns up --
7575
// if we did, we'd get a "multiple matching crates" error

src/librustc/metadata/loader.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ impl<'a> Context<'a> {
631631
}
632632

633633
fn find_commandline_library(&mut self) -> Option<Library> {
634-
let locs = match self.sess.opts.externs.find_equiv(&self.crate_name) {
634+
let locs = match self.sess.opts.externs.find_equiv(self.crate_name) {
635635
Some(s) => s,
636636
None => return None,
637637
};

src/librustc/middle/trans/base.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
224224
ty: Type,
225225
output: ty::t)
226226
-> ValueRef {
227-
match externs.find_equiv(&name) {
227+
match externs.find_equiv(name) {
228228
Some(n) => return *n,
229229
None => {}
230230
}
@@ -234,7 +234,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
234234
}
235235

236236
fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::DefId) -> ValueRef {
237-
match ccx.externs().borrow().find_equiv(&name) {
237+
match ccx.externs().borrow().find_equiv(name) {
238238
Some(n) => return *n,
239239
None => ()
240240
}
@@ -2999,7 +2999,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
29992999

30003000
let name = CString::new(llvm::LLVMGetValueName(val), false);
30013001
if !declared.contains(&name) &&
3002-
!reachable.contains_equiv(&name.as_str().unwrap()) {
3002+
!reachable.contains_equiv(name.as_str().unwrap()) {
30033003
llvm::SetLinkage(val, llvm::InternalLinkage);
30043004
}
30053005
}

src/librustc/middle/trans/debuginfo.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ fn declare_local(bcx: Block,
16701670
}
16711671

16721672
fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1673-
match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1673+
match debug_context(cx).created_files.borrow().find_equiv(full_path) {
16741674
Some(file_metadata) => return *file_metadata,
16751675
None => ()
16761676
}

src/librustc/middle/trans/type_.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl TypeNames {
333333
}
334334

335335
pub fn find_type(&self, s: &str) -> Option<Type> {
336-
self.named_types.borrow().find_equiv(&s).map(|x| Type::from_ref(*x))
336+
self.named_types.borrow().find_equiv(s).map(|x| Type::from_ref(*x))
337337
}
338338

339339
pub fn type_to_string(&self, ty: Type) -> String {

src/librustc/util/nodemap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub struct FnvHasher;
7474
pub struct FnvState(u64);
7575

7676
impl Hasher<FnvState> for FnvHasher {
77-
fn hash<T: Hash<FnvState>>(&self, t: &T) -> u64 {
77+
fn hash<Sized? T: Hash<FnvState>>(&self, t: &T) -> u64 {
7878
let mut state = FnvState(0xcbf29ce484222325);
7979
t.hash(&mut state);
8080
let FnvState(ret) = state;

src/librustdoc/html/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2123,7 +2123,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
21232123

21242124
fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
21252125
cur: &clean::Item, cx: &Context) -> fmt::Result {
2126-
let items = match cx.sidebar.find_equiv(&short) {
2126+
let items = match cx.sidebar.find_equiv(short) {
21272127
Some(items) => items.as_slice(),
21282128
None => return Ok(())
21292129
};

src/libstd/collections/hashmap/map.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use default::Default;
1717
use fmt::{mod, Show};
1818
use hash::{Hash, Hasher, RandomSipHasher};
1919
use iter::{mod, Iterator, FromIterator, Extendable};
20+
use kinds::Sized;
2021
use mem::{mod, replace};
2122
use num;
2223
use ops::{Deref, Index, IndexMut};
@@ -419,17 +420,17 @@ impl<K, V, M> SearchResult<K, V, M> {
419420
}
420421

421422
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
422-
fn make_hash<X: Hash<S>>(&self, x: &X) -> SafeHash {
423+
fn make_hash<Sized? X: Hash<S>>(&self, x: &X) -> SafeHash {
423424
table::make_hash(&self.hasher, x)
424425
}
425426

426-
fn search_equiv<'a, Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
427+
fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
427428
-> Option<FullBucketImm<'a, K, V>> {
428429
let hash = self.make_hash(q);
429430
search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option()
430431
}
431432

432-
fn search_equiv_mut<'a, Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
433+
fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
433434
-> Option<FullBucketMut<'a, K, V>> {
434435
let hash = self.make_hash(q);
435436
search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option()
@@ -857,15 +858,15 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
857858
/// using equivalence.
858859
///
859860
/// See [pop_equiv](#method.pop_equiv) for an extended example.
860-
pub fn contains_key_equiv<Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
861+
pub fn contains_key_equiv<Sized? Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
861862
self.search_equiv(key).is_some()
862863
}
863864

864865
/// Return the value corresponding to the key in the map, using
865866
/// equivalence.
866867
///
867868
/// See [pop_equiv](#method.pop_equiv) for an extended example.
868-
pub fn find_equiv<'a, Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
869+
pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
869870
match self.search_equiv(k) {
870871
None => None,
871872
Some(bucket) => {
@@ -921,7 +922,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
921922
///
922923
/// ```
923924
#[experimental]
924-
pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
925+
pub fn pop_equiv<Sized? Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
925926
if self.table.size() == 0 {
926927
return None
927928
}
@@ -1879,11 +1880,11 @@ mod test_map {
18791880
m.insert("baz".to_string(), baz);
18801881

18811882

1882-
assert_eq!(m.find_equiv(&("foo")), Some(&foo));
1883-
assert_eq!(m.find_equiv(&("bar")), Some(&bar));
1884-
assert_eq!(m.find_equiv(&("baz")), Some(&baz));
1883+
assert_eq!(m.find_equiv("foo"), Some(&foo));
1884+
assert_eq!(m.find_equiv("bar"), Some(&bar));
1885+
assert_eq!(m.find_equiv("baz"), Some(&baz));
18851886

1886-
assert_eq!(m.find_equiv(&("qux")), None);
1887+
assert_eq!(m.find_equiv("qux"), None);
18871888
}
18881889

18891890
#[test]

0 commit comments

Comments
 (0)