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]
This commit is contained in:
@@ -80,7 +80,7 @@ pub mod sip;
|
|||||||
/// A hashable type. The `S` type parameter is an abstract hash state that is
|
/// 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
|
/// used by the `Hash` to compute the hash. It defaults to
|
||||||
/// `std::hash::sip::SipState`.
|
/// `std::hash::sip::SipState`.
|
||||||
pub trait Hash<S = sip::SipState> {
|
pub trait Hash<S = sip::SipState> for Sized? {
|
||||||
/// Computes the hash of a value.
|
/// Computes the hash of a value.
|
||||||
fn hash(&self, state: &mut S);
|
fn hash(&self, state: &mut S);
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ pub trait Hash<S = sip::SipState> {
|
|||||||
/// containers like `HashMap`, which need a generic way hash multiple types.
|
/// containers like `HashMap`, which need a generic way hash multiple types.
|
||||||
pub trait Hasher<S> {
|
pub trait Hasher<S> {
|
||||||
/// Compute the hash of a value.
|
/// 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 {
|
pub trait Writer {
|
||||||
@@ -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]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
state.write(self.as_bytes());
|
state.write(self.as_bytes());
|
||||||
@@ -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)
|
||||||
impl_hash_tuple!(A B C D E F G H I J K L)
|
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]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
self.len().hash(state);
|
self.len().hash(state);
|
||||||
@@ -197,13 +197,6 @@ 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> {
|
impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
@@ -211,27 +204,28 @@ impl<S: Writer, T: Hash<S>> Hash<S> for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**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]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**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]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME (#18248) Make `T` `Sized?`
|
||||||
impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
|
impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
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> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use core::kinds::Sized;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use slice::ImmutableSlice;
|
use slice::ImmutableSlice;
|
||||||
@@ -301,7 +296,7 @@ mod tests {
|
|||||||
struct MyWriterHasher;
|
struct MyWriterHasher;
|
||||||
|
|
||||||
impl Hasher<MyWriter> for 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 };
|
let mut state = MyWriter { hash: 0 };
|
||||||
value.hash(&mut state);
|
value.hash(&mut state);
|
||||||
state.hash
|
state.hash
|
||||||
@@ -323,6 +318,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_writer_hasher() {
|
fn test_writer_hasher() {
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
let hasher = MyWriterHasher;
|
let hasher = MyWriterHasher;
|
||||||
|
|
||||||
assert_eq!(hasher.hash(&()), 0);
|
assert_eq!(hasher.hash(&()), 0);
|
||||||
@@ -344,9 +341,17 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(hasher.hash(&'a'), 97);
|
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];
|
let cs: &[u8] = &[1u8, 2u8, 3u8];
|
||||||
assert_eq!(hasher.hash(& cs), 9);
|
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 {
|
unsafe {
|
||||||
let ptr: *const int = mem::transmute(5i);
|
let ptr: *const int = mem::transmute(5i);
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ impl SipHasher {
|
|||||||
|
|
||||||
impl Hasher<SipState> for SipHasher {
|
impl Hasher<SipState> for SipHasher {
|
||||||
#[inline]
|
#[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);
|
let mut state = SipState::new_with_keys(self.k0, self.k1);
|
||||||
value.hash(&mut state);
|
value.hash(&mut state);
|
||||||
state.result()
|
state.result()
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#![stable]
|
#![stable]
|
||||||
|
|
||||||
|
use kinds::Sized;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
|
|
||||||
/// Trait for values that can be compared for equality and inequality.
|
/// Trait for values that can be compared for equality and inequality.
|
||||||
@@ -236,7 +237,7 @@ pub trait PartialOrd: PartialEq {
|
|||||||
/// container types; e.g. it is often desirable to be able to use `&str`
|
/// 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.
|
/// values to look up entries in a container with `String` keys.
|
||||||
#[experimental = "Better solutions may be discovered."]
|
#[experimental = "Better solutions may be discovered."]
|
||||||
pub trait Equiv<T> {
|
pub trait Equiv<T> for Sized? {
|
||||||
/// Implement this function to decide equivalent values.
|
/// Implement this function to decide equivalent values.
|
||||||
fn equiv(&self, other: &T) -> bool;
|
fn equiv(&self, other: &T) -> bool;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1565,7 +1565,7 @@ impl<'a,T:PartialEq> PartialEq for &'a [T] {
|
|||||||
impl<'a,T:Eq> Eq for &'a [T] {}
|
impl<'a,T:Eq> Eq for &'a [T] {}
|
||||||
|
|
||||||
#[unstable = "waiting for DST"]
|
#[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]
|
#[inline]
|
||||||
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
|
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1160,9 +1160,9 @@ pub mod traits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: Str> Equiv<S> for &'a str {
|
impl<S: Str> Equiv<S> for str {
|
||||||
#[inline]
|
#[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 {
|
impl ops::Slice<uint, str> for str {
|
||||||
|
|||||||
@@ -724,7 +724,7 @@ impl<'t> Captures<'t> {
|
|||||||
match self.named {
|
match self.named {
|
||||||
None => "",
|
None => "",
|
||||||
Some(ref h) => {
|
Some(ref h) => {
|
||||||
match h.find_equiv(&name) {
|
match h.find_equiv(name) {
|
||||||
None => "",
|
None => "",
|
||||||
Some(i) => self.at(*i),
|
Some(i) => self.at(*i),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ impl LintStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn register_renamed(&mut self, old_name: &str, new_name: &str) {
|
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(),
|
Some(&Id(lint_id)) => lint_id.clone(),
|
||||||
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
|
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
|
||||||
};
|
};
|
||||||
@@ -258,7 +258,7 @@ impl LintStore {
|
|||||||
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
|
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
|
||||||
-> Option<LintId>
|
-> 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(&Id(lint_id)) => Some(lint_id),
|
||||||
Some(&Renamed(ref new_name, lint_id)) => {
|
Some(&Renamed(ref new_name, lint_id)) => {
|
||||||
let warning = format!("lint {} has been renamed to {}",
|
let warning = format!("lint {} has been renamed to {}",
|
||||||
@@ -280,7 +280,7 @@ impl LintStore {
|
|||||||
None => {
|
None => {
|
||||||
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
|
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
|
||||||
.collect::<HashMap<&'static str, Vec<LintId>>>()
|
.collect::<HashMap<&'static str, Vec<LintId>>>()
|
||||||
.find_equiv(&lint_name.as_slice()) {
|
.find_equiv(lint_name.as_slice()) {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
v.iter()
|
v.iter()
|
||||||
.map(|lint_id: &LintId|
|
.map(|lint_id: &LintId|
|
||||||
@@ -487,7 +487,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
|
|||||||
match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
|
match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
|
||||||
Some(lint_id) => vec![(lint_id, level, span)],
|
Some(lint_id) => vec![(lint_id, level, span)],
|
||||||
None => {
|
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()
|
Some(&(ref v, _)) => v.iter()
|
||||||
.map(|lint_id: &LintId|
|
.map(|lint_id: &LintId|
|
||||||
(*lint_id, level, span))
|
(*lint_id, level, span))
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ fn existing_match(e: &Env, name: &str,
|
|||||||
// `source` stores paths which are normalized which may be different
|
// `source` stores paths which are normalized which may be different
|
||||||
// from the strings on the command line.
|
// from the strings on the command line.
|
||||||
let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
|
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) => {
|
Some(locs) => {
|
||||||
let found = locs.iter().any(|l| {
|
let found = locs.iter().any(|l| {
|
||||||
let l = fs::realpath(&Path::new(l.as_slice())).ok();
|
let l = fs::realpath(&Path::new(l.as_slice())).ok();
|
||||||
|
|||||||
@@ -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 {
|
fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
|
||||||
let name = reader::get_doc(item, tag_paths_data_name);
|
let name = reader::get_doc(item, tag_paths_data_name);
|
||||||
let string = name.as_str_slice();
|
let string = name.as_str_slice();
|
||||||
match intr.find_equiv(&string) {
|
match intr.find_equiv(string) {
|
||||||
None => token::intern(string),
|
None => token::intern(string),
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl<'a> FileSearch<'a> {
|
|||||||
debug!("filesearch: searching lib path");
|
debug!("filesearch: searching lib path");
|
||||||
let tlib_path = make_target_lib_path(self.sysroot,
|
let tlib_path = make_target_lib_path(self.sysroot,
|
||||||
self.triple);
|
self.triple);
|
||||||
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
|
if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
|
||||||
match f(&tlib_path) {
|
match f(&tlib_path) {
|
||||||
FileMatches => found = true,
|
FileMatches => found = true,
|
||||||
FileDoesntMatch => ()
|
FileDoesntMatch => ()
|
||||||
@@ -69,7 +69,7 @@ impl<'a> FileSearch<'a> {
|
|||||||
debug!("is {} in visited_dirs? {}", tlib_path.display(),
|
debug!("is {} in visited_dirs? {}", tlib_path.display(),
|
||||||
visited_dirs.contains_equiv(&tlib_path.as_vec().to_vec()));
|
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());
|
visited_dirs.insert(tlib_path.as_vec().to_vec());
|
||||||
// Don't keep searching the RUST_PATH if one match turns up --
|
// Don't keep searching the RUST_PATH if one match turns up --
|
||||||
// if we did, we'd get a "multiple matching crates" error
|
// if we did, we'd get a "multiple matching crates" error
|
||||||
|
|||||||
@@ -631,7 +631,7 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_commandline_library(&mut self) -> Option<Library> {
|
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,
|
Some(s) => s,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
|
|||||||
ty: Type,
|
ty: Type,
|
||||||
output: ty::t)
|
output: ty::t)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
match externs.find_equiv(&name) {
|
match externs.find_equiv(name) {
|
||||||
Some(n) => return *n,
|
Some(n) => return *n,
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@@ -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 {
|
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,
|
Some(n) => return *n,
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
@@ -2999,7 +2999,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
|
|||||||
|
|
||||||
let name = CString::new(llvm::LLVMGetValueName(val), false);
|
let name = CString::new(llvm::LLVMGetValueName(val), false);
|
||||||
if !declared.contains(&name) &&
|
if !declared.contains(&name) &&
|
||||||
!reachable.contains_equiv(&name.as_str().unwrap()) {
|
!reachable.contains_equiv(name.as_str().unwrap()) {
|
||||||
llvm::SetLinkage(val, llvm::InternalLinkage);
|
llvm::SetLinkage(val, llvm::InternalLinkage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1670,7 +1670,7 @@ fn declare_local(bcx: Block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
|
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,
|
Some(file_metadata) => return *file_metadata,
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ impl TypeNames {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_type(&self, s: &str) -> Option<Type> {
|
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 {
|
pub fn type_to_string(&self, ty: Type) -> String {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ pub struct FnvHasher;
|
|||||||
pub struct FnvState(u64);
|
pub struct FnvState(u64);
|
||||||
|
|
||||||
impl Hasher<FnvState> for FnvHasher {
|
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);
|
let mut state = FnvState(0xcbf29ce484222325);
|
||||||
t.hash(&mut state);
|
t.hash(&mut state);
|
||||||
let FnvState(ret) = state;
|
let FnvState(ret) = state;
|
||||||
|
|||||||
@@ -2123,7 +2123,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
|
|||||||
|
|
||||||
fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
|
fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
|
||||||
cur: &clean::Item, cx: &Context) -> fmt::Result {
|
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(),
|
Some(items) => items.as_slice(),
|
||||||
None => return Ok(())
|
None => return Ok(())
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use default::Default;
|
|||||||
use fmt::{mod, Show};
|
use fmt::{mod, Show};
|
||||||
use hash::{Hash, Hasher, RandomSipHasher};
|
use hash::{Hash, Hasher, RandomSipHasher};
|
||||||
use iter::{mod, Iterator, FromIterator, Extendable};
|
use iter::{mod, Iterator, FromIterator, Extendable};
|
||||||
|
use kinds::Sized;
|
||||||
use mem::{mod, replace};
|
use mem::{mod, replace};
|
||||||
use num;
|
use num;
|
||||||
use ops::{Deref, Index, IndexMut};
|
use ops::{Deref, Index, IndexMut};
|
||||||
@@ -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> {
|
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)
|
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>> {
|
-> Option<FullBucketImm<'a, K, V>> {
|
||||||
let hash = self.make_hash(q);
|
let hash = self.make_hash(q);
|
||||||
search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option()
|
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>> {
|
-> Option<FullBucketMut<'a, K, V>> {
|
||||||
let hash = self.make_hash(q);
|
let hash = self.make_hash(q);
|
||||||
search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option()
|
search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option()
|
||||||
@@ -857,7 +858,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
/// using equivalence.
|
/// using equivalence.
|
||||||
///
|
///
|
||||||
/// See [pop_equiv](#method.pop_equiv) for an extended example.
|
/// 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()
|
self.search_equiv(key).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,7 +866,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
/// equivalence.
|
/// equivalence.
|
||||||
///
|
///
|
||||||
/// See [pop_equiv](#method.pop_equiv) for an extended example.
|
/// 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) {
|
match self.search_equiv(k) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(bucket) => {
|
Some(bucket) => {
|
||||||
@@ -921,7 +922,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
#[experimental]
|
#[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 {
|
if self.table.size() == 0 {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
@@ -1879,11 +1880,11 @@ mod test_map {
|
|||||||
m.insert("baz".to_string(), baz);
|
m.insert("baz".to_string(), baz);
|
||||||
|
|
||||||
|
|
||||||
assert_eq!(m.find_equiv(&("foo")), Some(&foo));
|
assert_eq!(m.find_equiv("foo"), Some(&foo));
|
||||||
assert_eq!(m.find_equiv(&("bar")), Some(&bar));
|
assert_eq!(m.find_equiv("bar"), Some(&bar));
|
||||||
assert_eq!(m.find_equiv(&("baz")), Some(&baz));
|
assert_eq!(m.find_equiv("baz"), Some(&baz));
|
||||||
|
|
||||||
assert_eq!(m.find_equiv(&("qux")), None);
|
assert_eq!(m.find_equiv("qux"), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use cmp::{Eq, Equiv, PartialEq};
|
use cmp::{Eq, Equiv, PartialEq};
|
||||||
use collections::{Collection, Mutable, Set, MutableSet, Map, MutableMap};
|
use collections::{Collection, Mutable, Set, MutableSet, Map, MutableMap};
|
||||||
|
use core::kinds::Sized;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use fmt::Show;
|
use fmt::Show;
|
||||||
use fmt;
|
use fmt;
|
||||||
@@ -221,7 +222,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
|||||||
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
|
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
|
pub fn contains_equiv<Sized? Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
|
||||||
self.map.contains_key_equiv(value)
|
self.map.contains_key_equiv(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use clone::Clone;
|
|||||||
use cmp;
|
use cmp;
|
||||||
use hash::{Hash, Hasher};
|
use hash::{Hash, Hasher};
|
||||||
use iter::{Iterator, count};
|
use iter::{Iterator, count};
|
||||||
use kinds::marker;
|
use kinds::{Sized, marker};
|
||||||
use mem::{min_align_of, size_of};
|
use mem::{min_align_of, size_of};
|
||||||
use mem;
|
use mem;
|
||||||
use num::{CheckedAdd, CheckedMul, is_power_of_two};
|
use num::{CheckedAdd, CheckedMul, is_power_of_two};
|
||||||
@@ -131,7 +131,7 @@ impl SafeHash {
|
|||||||
/// We need to remove hashes of 0. That's reserved for empty buckets.
|
/// We need to remove hashes of 0. That's reserved for empty buckets.
|
||||||
/// This function wraps up `hash_keyed` to be the only way outside this
|
/// This function wraps up `hash_keyed` to be the only way outside this
|
||||||
/// module to generate a SafeHash.
|
/// module to generate a SafeHash.
|
||||||
pub fn make_hash<T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
|
pub fn make_hash<Sized? T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
|
||||||
match hasher.hash(t) {
|
match hasher.hash(t) {
|
||||||
// This constant is exceedingly likely to hash to the same
|
// This constant is exceedingly likely to hash to the same
|
||||||
// bucket, but it won't be counted as empty! Just so we can maintain
|
// bucket, but it won't be counted as empty! Just so we can maintain
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
|
|
||||||
pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
|
pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
|
||||||
|
|
||||||
|
use core::kinds::Sized;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand;
|
use rand;
|
||||||
@@ -91,7 +92,7 @@ impl RandomSipHasher {
|
|||||||
|
|
||||||
impl Hasher<sip::SipState> for RandomSipHasher {
|
impl Hasher<sip::SipState> for RandomSipHasher {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
|
fn hash<Sized? T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
|
||||||
self.hasher.hash(value)
|
self.hasher.hash(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,6 @@ impl Registry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_description(&self, code: &str) -> Option<&'static str> {
|
pub fn find_description(&self, code: &str) -> Option<&'static str> {
|
||||||
self.descriptions.find_equiv(&code).map(|desc| *desc)
|
self.descriptions.find_equiv(code).map(|desc| *desc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
|
|||||||
let name = interned_name.get();
|
let name = interned_name.get();
|
||||||
p.expect(&token::Eq);
|
p.expect(&token::Eq);
|
||||||
let e = p.parse_expr();
|
let e = p.parse_expr();
|
||||||
match names.find_equiv(&name) {
|
match names.find_equiv(name) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(prev) => {
|
Some(prev) => {
|
||||||
ecx.span_err(e.span,
|
ecx.span_err(e.span,
|
||||||
@@ -362,7 +362,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
|||||||
self.ecx.expr_path(path)
|
self.ecx.expr_path(path)
|
||||||
}
|
}
|
||||||
parse::CountIsName(n) => {
|
parse::CountIsName(n) => {
|
||||||
let i = match self.name_positions.find_equiv(&n) {
|
let i = match self.name_positions.find_equiv(n) {
|
||||||
Some(&i) => i,
|
Some(&i) => i,
|
||||||
None => 0, // error already emitted elsewhere
|
None => 0, // error already emitted elsewhere
|
||||||
};
|
};
|
||||||
@@ -406,7 +406,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
|||||||
// Named arguments are converted to positional arguments at
|
// Named arguments are converted to positional arguments at
|
||||||
// the end of the list of arguments
|
// the end of the list of arguments
|
||||||
parse::ArgumentNamed(n) => {
|
parse::ArgumentNamed(n) => {
|
||||||
let i = match self.name_positions.find_equiv(&n) {
|
let i = match self.name_positions.find_equiv(n) {
|
||||||
Some(&i) => i,
|
Some(&i) => i,
|
||||||
None => 0, // error already emitted elsewhere
|
None => 0, // error already emitted elsewhere
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> {
|
|||||||
(*vect).len()
|
(*vect).len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_equiv<Q:Hash + Equiv<T>>(&self, val: &Q) -> Option<Name> {
|
pub fn find_equiv<Sized? Q: Hash + Equiv<T>>(&self, val: &Q) -> Option<Name> {
|
||||||
let map = self.map.borrow();
|
let map = self.map.borrow();
|
||||||
match (*map).find_equiv(val) {
|
match (*map).find_equiv(val) {
|
||||||
Some(v) => Some(*v),
|
Some(v) => Some(*v),
|
||||||
@@ -149,7 +149,7 @@ impl StrInterner {
|
|||||||
|
|
||||||
pub fn intern(&self, val: &str) -> Name {
|
pub fn intern(&self, val: &str) -> Name {
|
||||||
let mut map = self.map.borrow_mut();
|
let mut map = self.map.borrow_mut();
|
||||||
match map.find_equiv(&val) {
|
match map.find_equiv(val) {
|
||||||
Some(&idx) => return idx,
|
Some(&idx) => return idx,
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ impl StrInterner {
|
|||||||
self.vect.borrow().len()
|
self.vect.borrow().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_equiv<Q:Hash + Equiv<RcStr>>(&self, val: &Q) -> Option<Name> {
|
pub fn find_equiv<Sized? Q:Hash + Equiv<RcStr>>(&self, val: &Q) -> Option<Name> {
|
||||||
match (*self.map.borrow()).find_equiv(val) {
|
match (*self.map.borrow()).find_equiv(val) {
|
||||||
Some(v) => Some(*v),
|
Some(v) => Some(*v),
|
||||||
None => None,
|
None => None,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
|||||||
if self.num_colors > color {
|
if self.num_colors > color {
|
||||||
let s = expand(self.ti
|
let s = expand(self.ti
|
||||||
.strings
|
.strings
|
||||||
.find_equiv(&("setaf"))
|
.find_equiv("setaf")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
[Number(color as int)], &mut Variables::new());
|
[Number(color as int)], &mut Variables::new());
|
||||||
@@ -95,7 +95,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
|||||||
if self.num_colors > color {
|
if self.num_colors > color {
|
||||||
let s = expand(self.ti
|
let s = expand(self.ti
|
||||||
.strings
|
.strings
|
||||||
.find_equiv(&("setab"))
|
.find_equiv("setab")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
[Number(color as int)], &mut Variables::new());
|
[Number(color as int)], &mut Variables::new());
|
||||||
@@ -113,7 +113,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
|||||||
attr::BackgroundColor(c) => self.bg(c),
|
attr::BackgroundColor(c) => self.bg(c),
|
||||||
_ => {
|
_ => {
|
||||||
let cap = cap_for_attr(attr);
|
let cap = cap_for_attr(attr);
|
||||||
let parm = self.ti.strings.find_equiv(&cap);
|
let parm = self.ti.strings.find_equiv(cap);
|
||||||
if parm.is_some() {
|
if parm.is_some() {
|
||||||
let s = expand(parm.unwrap().as_slice(),
|
let s = expand(parm.unwrap().as_slice(),
|
||||||
[],
|
[],
|
||||||
@@ -135,19 +135,19 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let cap = cap_for_attr(attr);
|
let cap = cap_for_attr(attr);
|
||||||
self.ti.strings.find_equiv(&cap).is_some()
|
self.ti.strings.find_equiv(cap).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self) -> IoResult<()> {
|
fn reset(&mut self) -> IoResult<()> {
|
||||||
let mut cap = self.ti.strings.find_equiv(&("sgr0"));
|
let mut cap = self.ti.strings.find_equiv("sgr0");
|
||||||
if cap.is_none() {
|
if cap.is_none() {
|
||||||
// are there any terminals that have color/attrs and not sgr0?
|
// are there any terminals that have color/attrs and not sgr0?
|
||||||
// Try falling back to sgr, then op
|
// Try falling back to sgr, then op
|
||||||
cap = self.ti.strings.find_equiv(&("sgr"));
|
cap = self.ti.strings.find_equiv("sgr");
|
||||||
if cap.is_none() {
|
if cap.is_none() {
|
||||||
cap = self.ti.strings.find_equiv(&("op"));
|
cap = self.ti.strings.find_equiv("op");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_string()), |op| {
|
let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_string()), |op| {
|
||||||
@@ -202,9 +202,9 @@ impl<T: Writer+Send> TerminfoTerminal<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let inf = ti.unwrap();
|
let inf = ti.unwrap();
|
||||||
let nc = if inf.strings.find_equiv(&("setaf")).is_some()
|
let nc = if inf.strings.find_equiv("setaf").is_some()
|
||||||
&& inf.strings.find_equiv(&("setab")).is_some() {
|
&& inf.strings.find_equiv("setab").is_some() {
|
||||||
inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
|
inf.numbers.find_equiv("colors").map_or(0, |&n| n)
|
||||||
} else { 0 };
|
} else { 0 };
|
||||||
|
|
||||||
return Some(box TerminfoTerminal {out: out,
|
return Some(box TerminfoTerminal {out: out,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ fn sort_and_fmt(mm: &HashMap<Vec<u8> , uint>, total: uint) -> String {
|
|||||||
// given a map, search for the frequency of a pattern
|
// given a map, search for the frequency of a pattern
|
||||||
fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint {
|
fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint {
|
||||||
let key = key.into_ascii().as_slice().to_lowercase().into_string();
|
let key = key.into_ascii().as_slice().to_lowercase().into_string();
|
||||||
match mm.find_equiv(&key.as_bytes()) {
|
match mm.find_equiv(key.as_bytes()) {
|
||||||
option::None => { return 0u; }
|
option::None => { return 0u; }
|
||||||
option::Some(&num) => { return num; }
|
option::Some(&num) => { return num; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ pub fn main() {
|
|||||||
assert!(!map.insert(Owned("cde".to_string()), c));
|
assert!(!map.insert(Owned("cde".to_string()), c));
|
||||||
assert!(!map.insert(Slice("def"), d));
|
assert!(!map.insert(Slice("def"), d));
|
||||||
|
|
||||||
assert_eq!(map.find_equiv(&("abc")), Some(&a));
|
assert_eq!(map.find_equiv("abc"), Some(&a));
|
||||||
assert_eq!(map.find_equiv(&("bcd")), Some(&b));
|
assert_eq!(map.find_equiv("bcd"), Some(&b));
|
||||||
assert_eq!(map.find_equiv(&("cde")), Some(&c));
|
assert_eq!(map.find_equiv("cde"), Some(&c));
|
||||||
assert_eq!(map.find_equiv(&("def")), Some(&d));
|
assert_eq!(map.find_equiv("def"), Some(&d));
|
||||||
|
|
||||||
assert_eq!(map.find_equiv(&Slice("abc")), Some(&a));
|
assert_eq!(map.find_equiv(&Slice("abc")), Some(&a));
|
||||||
assert_eq!(map.find_equiv(&Slice("bcd")), Some(&b));
|
assert_eq!(map.find_equiv(&Slice("bcd")), Some(&b));
|
||||||
|
|||||||
Reference in New Issue
Block a user