Skip to content

DSTify Hash #18440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions src/libcollections/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub mod sip;
/// A hashable type. The `S` type parameter is an abstract hash state that is
/// used by the `Hash` to compute the hash. It defaults to
/// `std::hash::sip::SipState`.
pub trait Hash<S = sip::SipState> {
pub trait Hash<S = sip::SipState> for Sized? {
/// Computes the hash of a value.
fn hash(&self, state: &mut S);
}
Expand All @@ -89,7 +89,7 @@ pub trait Hash<S = sip::SipState> {
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
/// Compute the hash of a value.
fn hash<T: Hash<S>>(&self, value: &T) -> u64;
fn hash<Sized? T: Hash<S>>(&self, value: &T) -> u64;
}

pub trait Writer {
Expand Down Expand Up @@ -137,7 +137,7 @@ impl<S: Writer> Hash<S> for char {
}
}

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

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


impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
#[inline]
fn hash(&self, state: &mut S) {
self.as_slice().hash(state);
}
}

impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
#[inline]
fn hash(&self, state: &mut S) {
self.as_slice().hash(state);
}
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a mut T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
impl<S: Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}

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

#[cfg(test)]
mod tests {
use core::kinds::Sized;
use std::mem;

use slice::ImmutableSlice;
Expand All @@ -301,7 +296,7 @@ mod tests {
struct MyWriterHasher;

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

#[test]
fn test_writer_hasher() {
use alloc::boxed::Box;

let hasher = MyWriterHasher;

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

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

assert_eq!(hasher.hash(&("a")), 97 + 0xFF);
let s: &str = "a";
assert_eq!(hasher.hash(& s), 97 + 0xFF);
// FIXME (#18283) Enable test
//let s: Box<str> = box "a";
//assert_eq!(hasher.hash(& s), 97 + 0xFF);
let cs: &[u8] = &[1u8, 2u8, 3u8];
assert_eq!(hasher.hash(& cs), 9);
let cs: Box<[u8]> = box [1u8, 2u8, 3u8];
assert_eq!(hasher.hash(& cs), 9);

// FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>

unsafe {
let ptr: *const int = mem::transmute(5i);
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/hash/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ impl SipHasher {

impl Hasher<SipState> for SipHasher {
#[inline]
fn hash<T: Hash<SipState>>(&self, value: &T) -> u64 {
fn hash<Sized? T: Hash<SipState>>(&self, value: &T) -> u64 {
let mut state = SipState::new_with_keys(self.k0, self.k1);
value.hash(&mut state);
state.result()
Expand Down
3 changes: 2 additions & 1 deletion src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#![stable]

use kinds::Sized;
use option::{Option, Some, None};

/// Trait for values that can be compared for equality and inequality.
Expand Down Expand Up @@ -236,7 +237,7 @@ pub trait PartialOrd: PartialEq {
/// container types; e.g. it is often desirable to be able to use `&str`
/// values to look up entries in a container with `String` keys.
#[experimental = "Better solutions may be discovered."]
pub trait Equiv<T> {
pub trait Equiv<T> for Sized? {
/// Implement this function to decide equivalent values.
fn equiv(&self, other: &T) -> bool;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@ impl<'a,T:PartialEq> PartialEq for &'a [T] {
impl<'a,T:Eq> Eq for &'a [T] {}

#[unstable = "waiting for DST"]
impl<'a,T:PartialEq, V: AsSlice<T>> Equiv<V> for &'a [T] {
impl<T: PartialEq, V: AsSlice<T>> Equiv<V> for [T] {
#[inline]
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,9 +1160,9 @@ pub mod traits {
}
}

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

impl ops::Slice<uint, str> for str {
Expand Down
2 changes: 1 addition & 1 deletion src/libregex/re.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ impl<'t> Captures<'t> {
match self.named {
None => "",
Some(ref h) => {
match h.find_equiv(&name) {
match h.find_equiv(name) {
None => "",
Some(i) => self.at(*i),
}
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl LintStore {
}

fn register_renamed(&mut self, old_name: &str, new_name: &str) {
let target = match self.by_name.find_equiv(&new_name) {
let target = match self.by_name.find_equiv(new_name) {
Some(&Id(lint_id)) => lint_id.clone(),
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
};
Expand Down Expand Up @@ -258,7 +258,7 @@ impl LintStore {
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
-> Option<LintId>
{
match self.by_name.find_equiv(&lint_name) {
match self.by_name.find_equiv(lint_name) {
Some(&Id(lint_id)) => Some(lint_id),
Some(&Renamed(ref new_name, lint_id)) => {
let warning = format!("lint {} has been renamed to {}",
Expand All @@ -280,7 +280,7 @@ impl LintStore {
None => {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
.collect::<HashMap<&'static str, Vec<LintId>>>()
.find_equiv(&lint_name.as_slice()) {
.find_equiv(lint_name.as_slice()) {
Some(v) => {
v.iter()
.map(|lint_id: &LintId|
Expand Down Expand Up @@ -487,7 +487,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
Some(lint_id) => vec![(lint_id, level, span)],
None => {
match self.lints.lint_groups.find_equiv(&lint_name.get()) {
match self.lints.lint_groups.find_equiv(lint_name.get()) {
Some(&(ref v, _)) => v.iter()
.map(|lint_id: &LintId|
(*lint_id, level, span))
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ fn existing_match(e: &Env, name: &str,
// `source` stores paths which are normalized which may be different
// from the strings on the command line.
let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
match e.sess.opts.externs.find_equiv(&name) {
match e.sess.opts.externs.find_equiv(name) {
Some(locs) => {
let found = locs.iter().any(|l| {
let l = fs::realpath(&Path::new(l.as_slice())).ok();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
let name = reader::get_doc(item, tag_paths_data_name);
let string = name.as_str_slice();
match intr.find_equiv(&string) {
match intr.find_equiv(string) {
None => token::intern(string),
Some(val) => val,
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/metadata/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a> FileSearch<'a> {
debug!("filesearch: searching lib path");
let tlib_path = make_target_lib_path(self.sysroot,
self.triple);
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
match f(&tlib_path) {
FileMatches => found = true,
FileDoesntMatch => ()
Expand All @@ -69,7 +69,7 @@ impl<'a> FileSearch<'a> {
debug!("is {} in visited_dirs? {}", tlib_path.display(),
visited_dirs.contains_equiv(&tlib_path.as_vec().to_vec()));

if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
visited_dirs.insert(tlib_path.as_vec().to_vec());
// Don't keep searching the RUST_PATH if one match turns up --
// if we did, we'd get a "multiple matching crates" error
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ impl<'a> Context<'a> {
}

fn find_commandline_library(&mut self) -> Option<Library> {
let locs = match self.sess.opts.externs.find_equiv(&self.crate_name) {
let locs = match self.sess.opts.externs.find_equiv(self.crate_name) {
Some(s) => s,
None => return None,
};
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
ty: Type,
output: ty::t)
-> ValueRef {
match externs.find_equiv(&name) {
match externs.find_equiv(name) {
Some(n) => return *n,
None => {}
}
Expand All @@ -234,7 +234,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
}

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

let name = CString::new(llvm::LLVMGetValueName(val), false);
if !declared.contains(&name) &&
!reachable.contains_equiv(&name.as_str().unwrap()) {
!reachable.contains_equiv(name.as_str().unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1670,7 +1670,7 @@ fn declare_local(bcx: Block,
}

fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
match debug_context(cx).created_files.borrow().find_equiv(full_path) {
Some(file_metadata) => return *file_metadata,
None => ()
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ impl TypeNames {
}

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

pub fn type_to_string(&self, ty: Type) -> String {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/util/nodemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub struct FnvHasher;
pub struct FnvState(u64);

impl Hasher<FnvState> for FnvHasher {
fn hash<T: Hash<FnvState>>(&self, t: &T) -> u64 {
fn hash<Sized? T: Hash<FnvState>>(&self, t: &T) -> u64 {
let mut state = FnvState(0xcbf29ce484222325);
t.hash(&mut state);
let FnvState(ret) = state;
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2123,7 +2123,7 @@ impl<'a> fmt::Show for Sidebar<'a> {

fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
cur: &clean::Item, cx: &Context) -> fmt::Result {
let items = match cx.sidebar.find_equiv(&short) {
let items = match cx.sidebar.find_equiv(short) {
Some(items) => items.as_slice(),
None => return Ok(())
};
Expand Down
21 changes: 11 additions & 10 deletions src/libstd/collections/hashmap/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use default::Default;
use fmt::{mod, Show};
use hash::{Hash, Hasher, RandomSipHasher};
use iter::{mod, Iterator, FromIterator, Extendable};
use kinds::Sized;
use mem::{mod, replace};
use num;
use ops::{Deref, Index, IndexMut};
Expand Down Expand Up @@ -419,17 +420,17 @@ impl<K, V, M> SearchResult<K, V, M> {
}

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

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

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

/// Return the value corresponding to the key in the map, using
/// equivalence.
///
/// See [pop_equiv](#method.pop_equiv) for an extended example.
pub fn find_equiv<'a, Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
match self.search_equiv(k) {
None => None,
Some(bucket) => {
Expand Down Expand Up @@ -921,7 +922,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
///
/// ```
#[experimental]
pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
pub fn pop_equiv<Sized? Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
if self.table.size() == 0 {
return None
}
Expand Down Expand Up @@ -1879,11 +1880,11 @@ mod test_map {
m.insert("baz".to_string(), baz);


assert_eq!(m.find_equiv(&("foo")), Some(&foo));
assert_eq!(m.find_equiv(&("bar")), Some(&bar));
assert_eq!(m.find_equiv(&("baz")), Some(&baz));
assert_eq!(m.find_equiv("foo"), Some(&foo));
assert_eq!(m.find_equiv("bar"), Some(&bar));
assert_eq!(m.find_equiv("baz"), Some(&baz));

assert_eq!(m.find_equiv(&("qux")), None);
assert_eq!(m.find_equiv("qux"), None);
}

#[test]
Expand Down
Loading