std: Stabilize the hash module

This commit is an implementation of [RFC 823][rfc] which is another pass over
the `std::hash` module for stabilization. The contents of the module were not
entirely marked stable, but some portions which remained quite similar to the
previous incarnation are now marked `#[stable]`. Specifically:

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0823-hash-simplification.md

* `std::hash` is now stable (the name)
* `Hash` is now stable
* `Hash::hash` is now stable
* `Hasher` is now stable
* `SipHasher` is now stable
* `SipHasher::new` and `new_with_keys` are now stable
* `Hasher for SipHasher` is now stable
* Many `Hash` implementations are now stable

All other portions of the `hash` module remain `#[unstable]` as they are less
commonly used and were recently redesigned.

This commit is a breaking change due to the modifications to the `std::hash` API
and more details can be found on the [RFC][rfc].

Closes #22467
[breaking-change]
This commit is contained in:
Alex Crichton 2015-02-17 20:48:07 -08:00
parent dfc5c0f1e8
commit f83e23ad7c
54 changed files with 5004 additions and 372 deletions

View File

@ -605,11 +605,19 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
fn default() -> Arc<T> { Arc::new(Default::default()) }
}
#[cfg(stage0)]
impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
fn hash(&self, state: &mut H) {
(**self).hash(state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for Arc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
#[cfg(test)]
mod tests {

View File

@ -10,13 +10,14 @@
//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Boxes are useful in two situations: recursive data structures, and occasionally when returning
//! data. [The Pointer chapter of the Book](../../../book/pointers.html#best-practices-1) explains
//! these cases in detail.
//! Boxes are useful in two situations: recursive data structures, and
//! occasionally when returning data. [The Pointer chapter of the
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
//! detail.
//!
//! # Examples
//!
@ -58,8 +59,8 @@ use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use core::raw::TraitObject;
/// A value that represents the heap. This is the default place that the `box` keyword allocates
/// into when no place is supplied.
/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
@ -219,12 +220,20 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}
#[cfg(stage0)]
impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
/// Extension methods for an owning `Any` trait object.
#[unstable(feature = "alloc",

View File

@ -73,7 +73,6 @@
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![feature(core)]
#![feature(hash)]
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
feature(libc))]

View File

@ -150,7 +150,7 @@ use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::hash::{Hasher, Hash};
use core::marker;
use core::mem::{transmute, min_align_of, size_of, forget};
use core::nonzero::NonZero;
@ -599,12 +599,20 @@ impl<T: Ord> Ord for Rc<T> {
}
// FIXME (#18248) Make `T` `Sized?`
impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
#[cfg(stage0)]
impl<S: Hasher, T: Hash<S>> Hash<S> for Rc<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for Rc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display> fmt::Display for Rc<T> {

View File

@ -984,6 +984,7 @@ impl fmt::Debug for Bitv {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
fn hash(&self, state: &mut S) {
self.nbits.hash(state);
@ -992,6 +993,16 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for Bitv {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.nbits.hash(state);
for elem in self.blocks() {
elem.hash(state);
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for Bitv {
@ -1756,6 +1767,7 @@ impl fmt::Debug for BitvSet {
}
}
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
fn hash(&self, state: &mut S) {
for pos in self {
@ -1763,6 +1775,15 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for BitvSet {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
for pos in self {
pos.hash(state);
}
}
}
/// An iterator for `BitvSet`.
#[derive(Clone)]

View File

@ -843,6 +843,7 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
fn hash(&self, state: &mut S) {
@ -851,6 +852,15 @@ impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
}
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
for elt in self {
elt.hash(state);
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Default for BTreeMap<K, V> {

View File

@ -27,7 +27,9 @@ use alloc::boxed::Box;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{Writer, Hasher, Hash};
use core::hash::{Hasher, Hash};
#[cfg(stage0)]
use core::hash::Writer;
use core::iter::{self, FromIterator, IntoIterator};
use core::mem;
use core::ptr;
@ -926,6 +928,7 @@ impl<A: fmt::Debug> fmt::Debug for DList<A> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
fn hash(&self, state: &mut S) {
self.len().hash(state);
@ -934,6 +937,16 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<A: Hash> Hash for DList<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for elt in self {
elt.hash(state);
}
}
}
#[cfg(test)]
mod tests {

View File

@ -26,7 +26,6 @@
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(hash)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]

View File

@ -31,7 +31,8 @@ use core::ops::{Index, IndexMut};
use core::ptr;
use core::raw::Slice as RawSlice;
use core::hash::{Writer, Hash, Hasher};
use core::hash::{Hash, Hasher};
#[cfg(stage0)] use core::hash::Writer;
use core::cmp;
use alloc::heap;
@ -1667,6 +1668,7 @@ impl<A: Ord> Ord for RingBuf<A> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
fn hash(&self, state: &mut S) {
self.len().hash(state);
@ -1675,6 +1677,16 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<A: Hash> Hash for RingBuf<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for elt in self {
elt.hash(state);
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> Index<usize> for RingBuf<A> {

View File

@ -833,12 +833,21 @@ impl fmt::Debug for String {
}
#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
#[cfg(stage0)]
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
#[inline]
fn hash(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl hash::Hash for String {
#[inline]
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]

View File

@ -1302,12 +1302,21 @@ impl<T:Clone> Clone for Vec<T> {
}
}
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<T: Hash> Hash for Vec<T> {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Index<usize> for Vec<T> {

View File

@ -20,7 +20,8 @@ use core::prelude::*;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{Hash, Writer, Hasher};
use core::hash::{Hash, Hasher};
#[cfg(stage0)] use core::hash::Writer;
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
use core::iter;
use core::mem::replace;
@ -99,6 +100,7 @@ impl<V> Default for VecMap<V> {
fn default() -> VecMap<V> { VecMap::new() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<V:Clone> Clone for VecMap<V> {
#[inline]
fn clone(&self) -> VecMap<V> {
@ -111,6 +113,7 @@ impl<V:Clone> Clone for VecMap<V> {
}
}
#[cfg(stage0)]
impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
fn hash(&self, state: &mut S) {
// In order to not traverse the `VecMap` twice, count the elements
@ -123,6 +126,20 @@ impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
count.hash(state);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
impl<V: Hash> Hash for VecMap<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
// In order to not traverse the `VecMap` twice, count the elements
// during iteration.
let mut count: usize = 0;
for elt in self {
elt.hash(state);
count += 1;
}
count.hash(state);
}
}
impl<V> VecMap<V> {
/// Creates an empty `VecMap`.

View File

@ -17,7 +17,7 @@
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use fmt;
use hash::{Hash, Hasher, self};
use hash::{Hash, self};
use iter::IntoIterator;
use marker::Copy;
use ops::Deref;
@ -35,11 +35,19 @@ macro_rules! array_impls {
}
}
impl<S: hash::Writer + Hasher, T: Hash<S>> Hash<S> for [T; $N] {
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
fn hash(&self, state: &mut S) {
Hash::hash(&self[], state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for [T; $N] {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Hash::hash(&self[], state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for [T; $N] {

View File

@ -35,7 +35,7 @@
//! the trait `Hash`:
//!
//! ```rust
//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher};
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//! id: uint,
@ -43,8 +43,8 @@
//! phone: u64,
//! }
//!
//! impl<H: Hasher + Writer> Hash<H> for Person {
//! fn hash(&self, state: &mut H) {
//! impl Hash for Person {
//! fn hash<H: Hasher>(&self, state: &mut H) {
//! self.id.hash(state);
//! self.phone.hash(state);
//! }
@ -56,15 +56,11 @@
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```
#![unstable(feature = "hash",
reason = "module was recently redesigned")]
#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use borrow::{Cow, ToOwned};
use default::Default;
use marker::Sized;
use mem;
use num::Int;
pub use self::sip::SipHasher;
@ -76,22 +72,123 @@ mod sip;
/// to compute the hash. Specific implementations of this trait may specialize
/// for particular instances of `H` in order to be able to optimize the hashing
/// behavior.
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
/// Feeds this value into the state given, updating the hasher as necessary.
#[stable(feature = "rust1", since = "1.0.0")]
fn hash<H: Hasher>(&self, state: &mut H);
/// Feeds a slice of this type into the state provided.
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
for piece in data {
piece.hash(state);
}
}
}
/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash. Specific implementations of this trait may specialize
/// for particular instances of `H` in order to be able to optimize the hashing
/// behavior.
#[cfg(stage0)]
pub trait Hash<H: Hasher> {
/// Feeds this value into the state given, updating the hasher as necessary.
fn hash(&self, state: &mut H);
}
/// A trait which represents the ability to hash an arbitrary stream of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
/// Result type of one run of hashing generated by this hasher.
#[cfg(stage0)]
type Output;
/// Resets this hasher back to its initial state (as if it were just
/// created).
#[cfg(stage0)]
fn reset(&mut self);
/// Completes a round of hashing, producing the output hash generated.
#[cfg(stage0)]
fn finish(&self) -> Self::Output;
/// Completes a round of hashing, producing the output hash generated.
#[cfg(not(stage0))]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn finish(&self) -> u64;
/// Writes some data into this `Hasher`
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]);
/// Write a single `u8` into this hasher
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_u8(&mut self, i: u8) { self.write(&[i]) }
/// Write a single `u16` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_u16(&mut self, i: u16) {
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
}
/// Write a single `u32` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_u32(&mut self, i: u32) {
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
}
/// Write a single `u64` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
}
/// Write a single `usize` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_usize(&mut self, i: usize) {
if cfg!(target_pointer_size = "32") {
self.write_u32(i as u32)
} else {
self.write_u64(i as u64)
}
}
/// Write a single `i8` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
/// Write a single `i16` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
/// Write a single `i32` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
/// Write a single `i64` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
/// Write a single `isize` into this hasher.
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
}
/// A common bound on the `Hasher` parameter to `Hash` implementations in order
@ -99,6 +196,7 @@ pub trait Hasher {
#[unstable(feature = "hash",
reason = "this trait will likely be replaced by io::Writer")]
#[allow(missing_docs)]
#[cfg(stage0)]
pub trait Writer {
fn write(&mut self, bytes: &[u8]);
}
@ -107,148 +205,312 @@ pub trait Writer {
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[cfg(stage0)]
pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
let mut h: H = Default::default();
value.hash(&mut h);
h.finish()
}
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[cfg(not(stage0))]
#[unstable(feature = "hash", reason = "module was recently redesigned")]
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
let mut h: H = Default::default();
value.hash(&mut h);
h.finish()
}
//////////////////////////////////////////////////////////////////////////////
macro_rules! impl_hash {
($ty:ident, $uty:ident) => {
impl<S: Writer + Hasher> Hash<S> for $ty {
#[inline]
fn hash(&self, state: &mut S) {
let a: [u8; ::$ty::BYTES] = unsafe {
mem::transmute((*self as $uty).to_le() as $ty)
};
state.write(&a)
}
}
}
}
#[cfg(stage0)]
mod impls {
use prelude::*;
impl_hash! { u8, u8 }
impl_hash! { u16, u16 }
impl_hash! { u32, u32 }
impl_hash! { u64, u64 }
impl_hash! { uint, uint }
impl_hash! { i8, u8 }
impl_hash! { i16, u16 }
impl_hash! { i32, u32 }
impl_hash! { i64, u64 }
impl_hash! { int, uint }
use borrow::{Cow, ToOwned};
use mem;
use num::Int;
use super::*;
impl<S: Writer + Hasher> Hash<S> for bool {
#[inline]
fn hash(&self, state: &mut S) {
(*self as u8).hash(state);
}
}
impl<S: Writer + Hasher> Hash<S> for char {
#[inline]
fn hash(&self, state: &mut S) {
(*self as u32).hash(state);
}
}
impl<S: Writer + Hasher> Hash<S> for str {
#[inline]
fn hash(&self, state: &mut S) {
state.write(self.as_bytes());
0xffu8.hash(state)
}
}
macro_rules! impl_hash_tuple {
() => (
impl<S: Hasher> Hash<S> for () {
#[inline]
fn hash(&self, _state: &mut S) {}
}
);
( $($name:ident)+) => (
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
#[inline]
#[allow(non_snake_case)]
fn hash(&self, state: &mut S) {
match *self {
($(ref $name,)*) => {
$(
$name.hash(state);
)*
}
macro_rules! impl_hash {
($ty:ident, $uty:ident) => {
impl<S: Writer + Hasher> Hash<S> for $ty {
#[inline]
fn hash(&self, state: &mut S) {
let a: [u8; ::$ty::BYTES] = unsafe {
mem::transmute((*self as $uty).to_le() as $ty)
};
state.write(&a)
}
}
}
);
}
}
impl_hash_tuple! {}
impl_hash_tuple! { A }
impl_hash_tuple! { A B }
impl_hash_tuple! { A B C }
impl_hash_tuple! { A B C D }
impl_hash_tuple! { A B C D E }
impl_hash_tuple! { A B C D E F }
impl_hash_tuple! { A B C D E F G }
impl_hash_tuple! { A B C D E F G H }
impl_hash_tuple! { A B C D E F G H I }
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_hash! { u8, u8 }
impl_hash! { u16, u16 }
impl_hash! { u32, u32 }
impl_hash! { u64, u64 }
impl_hash! { uint, uint }
impl_hash! { i8, u8 }
impl_hash! { i16, u16 }
impl_hash! { i32, u32 }
impl_hash! { i64, u64 }
impl_hash! { int, uint }
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
#[inline]
fn hash(&self, state: &mut S) {
self.len().hash(state);
for elt in self {
elt.hash(state);
impl<S: Writer + Hasher> Hash<S> for bool {
#[inline]
fn hash(&self, state: &mut S) {
(*self as u8).hash(state);
}
}
impl<S: Writer + Hasher> Hash<S> for char {
#[inline]
fn hash(&self, state: &mut S) {
(*self as u32).hash(state);
}
}
impl<S: Writer + Hasher> Hash<S> for str {
#[inline]
fn hash(&self, state: &mut S) {
state.write(self.as_bytes());
0xffu8.hash(state)
}
}
macro_rules! impl_hash_tuple {
() => (
impl<S: Hasher> Hash<S> for () {
#[inline]
fn hash(&self, _state: &mut S) {}
}
);
( $($name:ident)+) => (
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
#[inline]
#[allow(non_snake_case)]
fn hash(&self, state: &mut S) {
match *self {
($(ref $name,)*) => {
$(
$name.hash(state);
)*
}
}
}
}
);
}
impl_hash_tuple! {}
impl_hash_tuple! { A }
impl_hash_tuple! { A B }
impl_hash_tuple! { A B C }
impl_hash_tuple! { A B C D }
impl_hash_tuple! { A B C D E }
impl_hash_tuple! { A B C D E F }
impl_hash_tuple! { A B C D E F G }
impl_hash_tuple! { A B C D E F G H }
impl_hash_tuple! { A B C D E F G H I }
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<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
#[inline]
fn hash(&self, state: &mut S) {
self.len().hash(state);
for elt in self {
elt.hash(state);
}
}
}
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
impl<S: Writer + Hasher, T> Hash<S> for *const T {
#[inline]
fn hash(&self, state: &mut S) {
// NB: raw-pointer Hash does _not_ dereference
// to the target; it just gives you the pointer-bytes.
(*self as uint).hash(state);
}
}
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
#[inline]
fn hash(&self, state: &mut S) {
// NB: raw-pointer Hash does _not_ dereference
// to the target; it just gives you the pointer-bytes.
(*self as uint).hash(state);
}
}
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
where B: Hash<S> + ToOwned<T>
{
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
}
}
}
#[cfg(not(stage0))]
mod impls {
use prelude::*;
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
impl<S: Writer + Hasher, T> Hash<S> for *const T {
#[inline]
fn hash(&self, state: &mut S) {
// NB: raw-pointer Hash does _not_ dereference
// to the target; it just gives you the pointer-bytes.
(*self as uint).hash(state);
}
}
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
#[inline]
fn hash(&self, state: &mut S) {
// NB: raw-pointer Hash does _not_ dereference
// to the target; it just gives you the pointer-bytes.
(*self as uint).hash(state);
}
}
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
where B: Hash<S> + ToOwned<T>
{
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
use borrow::{Cow, ToOwned};
use slice;
use super::*;
macro_rules! impl_write {
($(($ty:ident, $meth:ident),)*) => {$(
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for $ty {
fn hash<H: Hasher>(&self, state: &mut H) {
state.$meth(*self)
}
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
let newlen = data.len() * ::$ty::BYTES;
let ptr = data.as_ptr() as *const u8;
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
}
}
)*}
}
impl_write! {
(u8, write_u8),
(u16, write_u16),
(u32, write_u32),
(u64, write_u64),
(usize, write_usize),
(i8, write_i8),
(i16, write_i16),
(i32, write_i32),
(i64, write_i64),
(isize, write_isize),
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for bool {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u8(*self as u8)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for char {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u32(*self as u32)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for str {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(self.as_bytes());
state.write_u8(0xff)
}
}
macro_rules! impl_hash_tuple {
() => (
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for () {
fn hash<H: Hasher>(&self, _state: &mut H) {}
}
);
( $($name:ident)+) => (
#[stable(feature = "rust1", since = "1.0.0")]
impl<$($name: Hash),*> Hash for ($($name,)*) {
#[allow(non_snake_case)]
fn hash<S: Hasher>(&self, state: &mut S) {
let ($(ref $name,)*) = *self;
$($name.hash(state);)*
}
}
);
}
impl_hash_tuple! {}
impl_hash_tuple! { A }
impl_hash_tuple! { A B }
impl_hash_tuple! { A B C }
impl_hash_tuple! { A B C D }
impl_hash_tuple! { A B C D E }
impl_hash_tuple! { A B C D E F }
impl_hash_tuple! { A B C D E F G }
impl_hash_tuple! { A B C D E F G H }
impl_hash_tuple! { A B C D E F G H I }
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 }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for [T] {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
Hash::hash_slice(self, state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + Hash> Hash for &'a T {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Hash for *const T {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(*self as usize)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Hash for *mut T {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(*self as usize)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, B: ?Sized> Hash for Cow<'a, T, B>
where B: Hash + ToOwned<T>
{
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}
}

View File

@ -15,7 +15,9 @@
use prelude::*;
use default::Default;
use super::{Hasher, Writer};
use super::Hasher;
#[cfg(stage0)]
use super::Writer;
/// An implementation of SipHash 2-4.
///
@ -30,6 +32,7 @@ use super::{Hasher, Writer};
/// strong, this implementation has not been reviewed for such purposes.
/// As such, all cryptographic uses of this implementation are strongly
/// discouraged.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
k0: u64,
k1: u64,
@ -88,12 +91,14 @@ macro_rules! compress {
impl SipHasher {
/// Creates a new `SipHasher` with the two initial keys set to 0.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> SipHasher {
SipHasher::new_with_keys(0, 0)
}
/// Creates a `SipHasher` that is keyed off the provided keys.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
let mut state = SipHasher {
k0: key0,
@ -114,10 +119,16 @@ impl SipHasher {
#[unstable(feature = "hash")]
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
pub fn result(&self) -> u64 { self.finish() }
}
impl Writer for SipHasher {
#[inline]
fn reset(&mut self) {
self.length = 0;
self.v0 = self.k0 ^ 0x736f6d6570736575;
self.v1 = self.k1 ^ 0x646f72616e646f6d;
self.v2 = self.k0 ^ 0x6c7967656e657261;
self.v3 = self.k1 ^ 0x7465646279746573;
self.ntail = 0;
}
fn write(&mut self, msg: &[u8]) {
let length = msg.len();
self.length += length;
@ -164,16 +175,28 @@ impl Writer for SipHasher {
}
}
#[cfg(stage0)]
impl Writer for SipHasher {
#[inline]
fn write(&mut self, msg: &[u8]) {
self.write(msg)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
#[cfg(stage0)]
type Output = u64;
#[cfg(stage0)]
fn reset(&mut self) {
self.length = 0;
self.v0 = self.k0 ^ 0x736f6d6570736575;
self.v1 = self.k1 ^ 0x646f72616e646f6d;
self.v2 = self.k0 ^ 0x6c7967656e657261;
self.v3 = self.k1 ^ 0x7465646279746573;
self.ntail = 0;
self.reset();
}
#[inline]
#[cfg(not(stage0))]
fn write(&mut self, msg: &[u8]) {
self.write(msg)
}
fn finish(&self) -> u64 {
@ -199,6 +222,7 @@ impl Hasher for SipHasher {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
#[inline]
fn clone(&self) -> SipHasher {
@ -216,6 +240,7 @@ impl Clone for SipHasher {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
fn default() -> SipHasher {
SipHasher::new()

View File

@ -9,7 +9,7 @@
// except according to those terms.
use std::mem;
use std::hash::{Hash, Hasher, Writer};
use std::hash::{Hash, Hasher};
use std::default::Default;
struct MyHasher {
@ -22,25 +22,20 @@ impl Default for MyHasher {
}
}
impl Writer for MyHasher {
// Most things we'll just add up the bytes.
impl Hasher for MyHasher {
type Output = u64;
fn write(&mut self, buf: &[u8]) {
for byte in buf {
self.hash += *byte as u64;
}
}
}
impl Hasher for MyHasher {
type Output = u64;
fn reset(&mut self) { self.hash = 0; }
fn finish(&self) -> u64 { self.hash }
}
#[test]
fn test_writer_hasher() {
fn hash<T: Hash<MyHasher>>(t: &T) -> u64 {
fn hash<T: Hash>(t: &T) -> u64 {
::std::hash::hash::<_, MyHasher>(t)
}
@ -91,8 +86,9 @@ struct CustomHasher { output: u64 }
impl Hasher for CustomHasher {
type Output = u64;
fn reset(&mut self) { self.output = 0; }
fn finish(&self) -> u64 { self.output }
fn write(&mut self, data: &[u8]) { panic!() }
fn write_u64(&mut self, data: u64) { self.output = data; }
}
impl Default for CustomHasher {
@ -101,15 +97,15 @@ impl Default for CustomHasher {
}
}
impl Hash<CustomHasher> for Custom {
fn hash(&self, state: &mut CustomHasher) {
state.output = self.hash;
impl Hash for Custom {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.hash);
}
}
#[test]
fn test_custom_state() {
fn hash<T: Hash<CustomHasher>>(t: &T) -> u64 {
fn hash<T: Hash>(t: &T) -> u64 {
::std::hash::hash::<_, CustomHasher>(t)
}

View File

@ -185,12 +185,20 @@ impl PartialEq for LintId {
impl Eq for LintId { }
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
fn hash(&self, state: &mut S) {
let ptr = self.lint as *const Lint;
ptr.hash(state);
}
}
#[cfg(not(stage0))]
impl hash::Hash for LintId {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
let ptr = self.lint as *const Lint;
ptr.hash(state);
}
}
impl LintId {
/// Get the `LintId` for a `Lint`.

View File

@ -1588,6 +1588,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
// Path and definition ID indexing
#[cfg(stage0)]
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
F: FnMut(&mut SeekableMemWriter, &T),
T: Hash<SipHasher>,
@ -1628,6 +1629,47 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn:
rbml_w.end_tag();
rbml_w.end_tag();
}
#[cfg(not(stage0))]
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
F: FnMut(&mut SeekableMemWriter, &T),
T: Hash,
{
let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
for elt in index {
let mut s = SipHasher::new();
elt.val.hash(&mut s);
let h = s.finish() as uint;
(&mut buckets[h % 256]).push(elt);
}
rbml_w.start_tag(tag_index);
let mut bucket_locs = Vec::new();
rbml_w.start_tag(tag_index_buckets);
for bucket in &buckets {
bucket_locs.push(rbml_w.writer.tell().unwrap());
rbml_w.start_tag(tag_index_buckets_bucket);
for elt in bucket {
rbml_w.start_tag(tag_index_buckets_bucket_elt);
assert!(elt.pos < 0xffff_ffff);
{
let wr: &mut SeekableMemWriter = rbml_w.writer;
wr.write_be_u32(elt.pos as u32);
}
write_fn(rbml_w.writer, &elt.val);
rbml_w.end_tag();
}
rbml_w.end_tag();
}
rbml_w.end_tag();
rbml_w.start_tag(tag_index_table);
for pos in &bucket_locs {
assert!(*pos < 0xffff_ffff);
let wr: &mut SeekableMemWriter = rbml_w.writer;
wr.write_be_u32(*pos as u32);
}
rbml_w.end_tag();
rbml_w.end_tag();
}
fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
let wr: &mut SeekableMemWriter = writer;

View File

@ -72,7 +72,8 @@ use std::borrow::{BorrowFrom, Cow};
use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt;
use std::hash::{Hash, Writer, SipHasher, Hasher};
use std::hash::{Hash, SipHasher, Hasher};
#[cfg(stage0)] use std::hash::Writer;
use std::mem;
use std::ops;
use std::rc::Rc;
@ -958,11 +959,18 @@ impl<'tcx> PartialEq for TyS<'tcx> {
}
impl<'tcx> Eq for TyS<'tcx> {}
#[cfg(stage0)]
impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
fn hash(&self, s: &mut S) {
(self as *const _).hash(s)
}
}
#[cfg(not(stage0))]
impl<'tcx> Hash for TyS<'tcx> {
fn hash<H: Hasher>(&self, s: &mut H) {
(self as *const _).hash(s)
}
}
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
@ -980,11 +988,18 @@ impl<'tcx> PartialEq for InternedTy<'tcx> {
impl<'tcx> Eq for InternedTy<'tcx> {}
#[cfg(stage0)]
impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
fn hash(&self, s: &mut S) {
self.ty.sty.hash(s)
}
}
#[cfg(not(stage0))]
impl<'tcx> Hash for InternedTy<'tcx> {
fn hash<H: Hasher>(&self, s: &mut H) {
self.ty.sty.hash(s)
}
}
impl<'tcx> BorrowFrom<InternedTy<'tcx>> for sty<'tcx> {
fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> {

View File

@ -13,7 +13,8 @@
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::hash::Hash;
#[cfg(stage0)] use std::hash::Hasher;
use std::iter::repeat;
use std::time::Duration;
use std::collections::hash_state::HashState;
@ -144,11 +145,54 @@ pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -
/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
/// very small graphs. If the graphs become larger, a more efficient graph representation and
/// algorithm would probably be advised.
#[cfg(stage0)]
pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
destination: T) -> bool
where S: HashState,
<S as HashState>::Hasher: Hasher<Output=u64>,
T: Hash< <S as HashState>::Hasher> + Eq + Clone,
T: Hash<<S as HashState>::Hasher> + Eq + Clone,
{
if source == destination {
return true;
}
// Do a little breadth-first-search here. The `queue` list
// doubles as a way to detect if we've seen a particular FR
// before. Note that we expect this graph to be an *extremely
// shallow* tree.
let mut queue = vec!(source);
let mut i = 0;
while i < queue.len() {
match edges_map.get(&queue[i]) {
Some(edges) => {
for target in edges {
if *target == destination {
return true;
}
if !queue.iter().any(|x| x == target) {
queue.push((*target).clone());
}
}
}
None => {}
}
i += 1;
}
return false;
}
/// K: Eq + Hash<S>, V, S, H: Hasher<S>
///
/// Determines whether there exists a path from `source` to `destination`. The graph is defined by
/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`.
///
/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
/// very small graphs. If the graphs become larger, a more efficient graph representation and
/// algorithm would probably be advised.
#[cfg(not(stage0))]
pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
destination: T) -> bool
where S: HashState, T: Hash + Eq + Clone,
{
if source == destination {
return true;
@ -206,6 +250,7 @@ pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
/// }
/// ```
#[inline(always)]
#[cfg(stage0)]
pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
where T: Clone + Hash<<S as HashState>::Hasher> + Eq,
U: Clone,
@ -224,3 +269,47 @@ pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) ->
}
}
}
/// Memoizes a one-argument closure using the given RefCell containing
/// a type implementing MutableMap to serve as a cache.
///
/// In the future the signature of this function is expected to be:
/// ```
/// pub fn memoized<T: Clone, U: Clone, M: MutableMap<T, U>>(
/// cache: &RefCell<M>,
/// f: &|T| -> U
/// ) -> impl |T| -> U {
/// ```
/// but currently it is not possible.
///
/// # Example
/// ```
/// struct Context {
/// cache: RefCell<HashMap<uint, uint>>
/// }
///
/// fn factorial(ctxt: &Context, n: uint) -> uint {
/// memoized(&ctxt.cache, n, |n| match n {
/// 0 | 1 => n,
/// _ => factorial(ctxt, n - 2) + factorial(ctxt, n - 1)
/// })
/// }
/// ```
#[inline(always)]
#[cfg(not(stage0))]
pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
where T: Clone + Hash + Eq,
U: Clone,
S: HashState,
F: FnOnce(T) -> U,
{
let key = arg.clone();
let result = cache.borrow().get(&key).map(|result| result.clone());
match result {
Some(result) => result,
None => {
let result = f(arg);
cache.borrow_mut().insert(key, result.clone());
result
}
}
}

View File

@ -15,7 +15,8 @@
use std::collections::hash_state::{DefaultState};
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::hash::{Hasher, Writer, Hash};
use std::hash::{Hasher, Hash};
#[cfg(stage0)] use std::hash::Writer;
use syntax::ast;
pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
@ -27,12 +28,22 @@ pub type DefIdMap<T> = FnvHashMap<ast::DefId, T>;
pub type NodeSet = FnvHashSet<ast::NodeId>;
pub type DefIdSet = FnvHashSet<ast::DefId>;
#[cfg(stage0)]
pub fn FnvHashMap<K: Hash<FnvHasher> + Eq, V>() -> FnvHashMap<K, V> {
Default::default()
}
#[cfg(stage0)]
pub fn FnvHashSet<V: Hash<FnvHasher> + Eq>() -> FnvHashSet<V> {
Default::default()
}
#[cfg(not(stage0))]
pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
Default::default()
}
#[cfg(not(stage0))]
pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
Default::default()
}
pub fn NodeMap<T>() -> NodeMap<T> { FnvHashMap() }
pub fn DefIdMap<T>() -> DefIdMap<T> { FnvHashMap() }
@ -52,12 +63,14 @@ impl Default for FnvHasher {
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
}
#[cfg(stage0)]
impl Hasher for FnvHasher {
type Output = u64;
fn reset(&mut self) { *self = Default::default(); }
fn finish(&self) -> u64 { self.0 }
}
#[cfg(stage0)]
impl Writer for FnvHasher {
fn write(&mut self, bytes: &[u8]) {
let FnvHasher(mut hash) = *self;
@ -68,3 +81,16 @@ impl Writer for FnvHasher {
*self = FnvHasher(hash);
}
}
#[cfg(not(stage0))]
impl Hasher for FnvHasher {
fn write(&mut self, bytes: &[u8]) {
let FnvHasher(mut hash) = *self;
for byte in bytes {
hash = hash ^ (*byte as u64);
hash = hash * 0x100000001b3;
}
*self = FnvHasher(hash);
}
fn finish(&self) -> u64 { self.0 }
}

View File

@ -28,7 +28,8 @@ use middle::ty_fold::TypeFoldable;
use std::collections::HashMap;
use std::collections::hash_state::HashState;
use std::hash::{Hash, Hasher};
use std::hash::Hash;
#[cfg(stage0)] use std::hash::Hasher;
use std::rc::Rc;
use syntax::abi;
use syntax::ast_map;
@ -1420,6 +1421,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
}
}
#[cfg(stage0)]
impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
where K: Hash<<S as HashState>::Hasher> + Eq + Repr<'tcx>,
V: Repr<'tcx>,
@ -1435,6 +1437,21 @@ impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
}
}
#[cfg(not(stage0))]
impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
where K: Hash + Eq + Repr<'tcx>,
V: Repr<'tcx>,
S: HashState,
{
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("HashMap({})",
self.iter()
.map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx)))
.collect::<Vec<String>>()
.connect(", "))
}
}
impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate<T,U>
where T : Repr<'tcx> + TypeFoldable<'tcx>,
U : Repr<'tcx> + TypeFoldable<'tcx>,

View File

@ -20,7 +20,6 @@
#![allow(non_camel_case_types)]
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]

View File

@ -25,7 +25,6 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(libc)]
#![feature(link_args)]

View File

@ -20,7 +20,6 @@
#![feature(alloc)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]

View File

@ -28,7 +28,6 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(env)]

View File

@ -23,7 +23,6 @@
#![feature(collections)]
#![feature(core)]
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(libc)]

View File

@ -12,7 +12,8 @@
use std::usize;
use std::default::Default;
use std::hash::{Hash, Hasher};
use std::hash::Hash;
#[cfg(stage0)] use std::hash::Hasher;
use std::collections::hash_state::HashState;
use {Decodable, Encodable, Decoder, Encoder};
@ -157,6 +158,7 @@ impl<
}
}
#[cfg(stage0)]
impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash< <S as HashState>::Hasher> + Eq,
V: Encodable,
@ -175,7 +177,26 @@ impl<K, V, S> Encodable for HashMap<K, V, S>
})
}
}
#[cfg(not(stage0))]
impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash + Eq,
V: Encodable,
S: HashState,
{
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_map(self.len(), |e| {
let mut i = 0;
for (key, val) in self {
try!(e.emit_map_elt_key(i, |e| key.encode(e)));
try!(e.emit_map_elt_val(i, |e| val.encode(e)));
i += 1;
}
Ok(())
})
}
}
#[cfg(stage0)]
impl<K, V, S> Decodable for HashMap<K, V, S>
where K: Decodable + Hash< <S as HashState>::Hasher> + Eq,
V: Decodable,
@ -195,7 +216,27 @@ impl<K, V, S> Decodable for HashMap<K, V, S>
})
}
}
#[cfg(not(stage0))]
impl<K, V, S> Decodable for HashMap<K, V, S>
where K: Decodable + Hash + Eq,
V: Decodable,
S: HashState + Default,
{
fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
d.read_map(|d, len| {
let state = Default::default();
let mut map = HashMap::with_capacity_and_hash_state(len, state);
for i in 0..len {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
Ok(map)
})
}
}
#[cfg(stage0)]
impl<T, S> Encodable for HashSet<T, S>
where T: Encodable + Hash< <S as HashState>::Hasher> + Eq,
S: HashState,
@ -212,7 +253,24 @@ impl<T, S> Encodable for HashSet<T, S>
})
}
}
#[cfg(not(stage0))]
impl<T, S> Encodable for HashSet<T, S>
where T: Encodable + Hash + Eq,
S: HashState,
{
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
let mut i = 0;
for e in self {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
i += 1;
}
Ok(())
})
}
}
#[cfg(stage0)]
impl<T, S> Decodable for HashSet<T, S>
where T: Decodable + Hash< <S as HashState>::Hasher> + Eq,
S: HashState + Default,
@ -229,6 +287,22 @@ impl<T, S> Decodable for HashSet<T, S>
})
}
}
#[cfg(not(stage0))]
impl<T, S> Decodable for HashSet<T, S>
where T: Decodable + Hash + Eq,
S: HashState + Default,
{
fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
d.read_seq(|d, len| {
let state = Default::default();
let mut set = HashSet::with_capacity_and_hash_state(len, state);
for i in 0..len {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
})
}
}
impl<V: Encodable> Encodable for VecMap<V> {
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {

View File

@ -31,7 +31,6 @@ Core encoding and decoding interfaces.
#![feature(int_uint)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(hash)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(std_misc)]

View File

@ -19,7 +19,7 @@ use clone::Clone;
use cmp::{max, Eq, PartialEq};
use default::Default;
use fmt::{self, Debug};
use hash::{self, Hash, SipHasher};
use hash::{Hash, SipHasher};
use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
use marker::Sized;
use mem::{self, replace};
@ -440,12 +440,10 @@ impl<K, V, M> SearchResult<K, V, M> {
}
}
impl<K, V, S, H> HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash<H> {
fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash {
table::make_hash(&self.hash_state, x)
}
@ -453,7 +451,7 @@ impl<K, V, S, H> HashMap<K, V, S>
/// If you already have the hash for the key lying around, use
/// search_hashed.
fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
where Q: BorrowFrom<K> + Eq + Hash<H>
where Q: BorrowFrom<K> + Eq + Hash
{
let hash = self.make_hash(q);
search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
@ -461,7 +459,7 @@ impl<K, V, S, H> HashMap<K, V, S>
}
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
where Q: BorrowFrom<K> + Eq + Hash<H>
where Q: BorrowFrom<K> + Eq + Hash
{
let hash = self.make_hash(q);
search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
@ -490,7 +488,7 @@ impl<K, V, S, H> HashMap<K, V, S>
}
}
impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
/// Create an empty HashMap.
///
/// # Example
@ -520,10 +518,8 @@ impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
}
}
impl<K, V, S, H> HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
/// Creates an empty hashmap which will use the given hasher to hash keys.
///
@ -1037,7 +1033,7 @@ impl<K, V, S, H> HashMap<K, V, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where Q: Hash<H> + Eq + BorrowFrom<K>
where Q: Hash + Eq + BorrowFrom<K>
{
self.search(k).map(|bucket| bucket.into_refs().1)
}
@ -1060,7 +1056,7 @@ impl<K, V, S, H> HashMap<K, V, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where Q: Hash<H> + Eq + BorrowFrom<K>
where Q: Hash + Eq + BorrowFrom<K>
{
self.search(k).is_some()
}
@ -1086,7 +1082,7 @@ impl<K, V, S, H> HashMap<K, V, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where Q: Hash<H> + Eq + BorrowFrom<K>
where Q: Hash + Eq + BorrowFrom<K>
{
self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
}
@ -1138,7 +1134,7 @@ impl<K, V, S, H> HashMap<K, V, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
where Q: Hash<H> + Eq + BorrowFrom<K>
where Q: Hash + Eq + BorrowFrom<K>
{
if self.table.size() == 0 {
return None
@ -1195,10 +1191,8 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
}
}
impl<K, V, S, H> PartialEq for HashMap<K, V, S>
where K: Eq + Hash<H>, V: PartialEq,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> PartialEq for HashMap<K, V, S>
where K: Eq + Hash, V: PartialEq, S: HashState
{
fn eq(&self, other: &HashMap<K, V, S>) -> bool {
if self.len() != other.len() { return false; }
@ -1210,17 +1204,13 @@ impl<K, V, S, H> PartialEq for HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> Eq for HashMap<K, V, S>
where K: Eq + Hash<H>, V: Eq,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> Eq for HashMap<K, V, S>
where K: Eq + Hash, V: Eq, S: HashState
{}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> Debug for HashMap<K, V, S>
where K: Eq + Hash<H> + Debug, V: Debug,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> Debug for HashMap<K, V, S>
where K: Eq + Hash + Debug, V: Debug, S: HashState
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "HashMap {{"));
@ -1235,10 +1225,9 @@ impl<K, V, S, H> Debug for HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> Default for HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<K, V, S> Default for HashMap<K, V, S>
where K: Eq + Hash,
S: HashState + Default,
{
fn default() -> HashMap<K, V, S> {
HashMap::with_hash_state(Default::default())
@ -1246,11 +1235,10 @@ impl<K, V, S, H> Default for HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
where K: Eq + Hash<H>,
Q: Eq + Hash<H> + BorrowFrom<K>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, Q: ?Sized, V, S> Index<Q> for HashMap<K, V, S>
where K: Eq + Hash,
Q: Eq + Hash + BorrowFrom<K>,
S: HashState,
{
type Output = V;
@ -1261,11 +1249,10 @@ impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
where K: Eq + Hash<H>,
Q: Eq + Hash<H> + BorrowFrom<K>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
where K: Eq + Hash,
Q: Eq + Hash + BorrowFrom<K>,
S: HashState,
{
#[inline]
fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
@ -1373,10 +1360,8 @@ enum VacantEntryState<K, V, M> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
@ -1387,10 +1372,8 @@ impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
@ -1401,10 +1384,8 @@ impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> IntoIterator for HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
@ -1550,10 +1531,8 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
where K: Eq + Hash, S: HashState + Default
{
fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
let lower = iter.size_hint().0;
@ -1565,10 +1544,8 @@ impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
fn extend<T: Iterator<Item=(K, V)>>(&mut self, iter: T) {
for (k, v) in iter {
@ -1606,9 +1583,9 @@ impl RandomState {
#[unstable(feature = "std_misc",
reason = "hashing an hash maps may be altered")]
impl HashState for RandomState {
type Hasher = Hasher;
fn hasher(&self) -> Hasher {
Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) }
type Hasher = SipHasher;
fn hasher(&self) -> SipHasher {
SipHasher::new_with_keys(self.k0, self.k1)
}
}
@ -1621,25 +1598,6 @@ impl Default for RandomState {
}
}
/// A hasher implementation which is generated from `RandomState` instances.
///
/// This is the default hasher used in a `HashMap` to hash keys. Types do not
/// typically declare an ability to explicitly hash into this particular type,
/// but rather in a `H: hash::Writer` type parameter.
#[unstable(feature = "std_misc",
reason = "hashing an hash maps may be altered")]
pub struct Hasher { inner: SipHasher }
impl hash::Writer for Hasher {
fn write(&mut self, data: &[u8]) { self.inner.write(data) }
}
impl hash::Hasher for Hasher {
type Output = u64;
fn reset(&mut self) { self.inner.reset() }
fn finish(&self) -> u64 { self.inner.finish() }
}
#[cfg(test)]
mod test_map {
use prelude::v1::*;

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,14 @@
mod bench;
mod table;
#[cfg(stage0)]
#[path = "map_stage0.rs"]
pub mod map;
#[cfg(not(stage0))]
pub mod map;
#[cfg(stage0)]
#[path = "set_stage0.rs"]
pub mod set;
#[cfg(not(stage0))]
pub mod set;
pub mod state;

View File

@ -17,14 +17,14 @@ use core::marker::Sized;
use default::Default;
use fmt::Debug;
use fmt;
use hash::{self, Hash};
use hash::Hash;
use iter::{
Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend,
};
use ops::{BitOr, BitAnd, BitXor, Sub};
use option::Option::{Some, None, self};
use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher};
use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState};
use super::state::HashState;
// Future Optimization (FIXME!)
@ -97,7 +97,7 @@ pub struct HashSet<T, S = RandomState> {
map: HashMap<T, (), S>
}
impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
impl<T: Hash + Eq> HashSet<T, RandomState> {
/// Create an empty HashSet.
///
/// # Example
@ -128,10 +128,8 @@ impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
}
}
impl<T, S, H> HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> HashSet<T, S>
where T: Eq + Hash, S: HashState
{
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
@ -462,7 +460,7 @@ impl<T, S, H> HashSet<T, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<H> + Eq
where Q: BorrowFrom<T> + Hash + Eq
{
self.map.contains_key(value)
}
@ -572,17 +570,15 @@ impl<T, S, H> HashSet<T, S>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<H> + Eq
where Q: BorrowFrom<T> + Hash + Eq
{
self.map.remove(value).is_some()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> PartialEq for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> PartialEq for HashSet<T, S>
where T: Eq + Hash, S: HashState
{
fn eq(&self, other: &HashSet<T, S>) -> bool {
if self.len() != other.len() { return false; }
@ -592,17 +588,14 @@ impl<T, S, H> PartialEq for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> Eq for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> Eq for HashSet<T, S>
where T: Eq + Hash, S: HashState
{}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> fmt::Debug for HashSet<T, S>
where T: Eq + Hash<H> + fmt::Debug,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> fmt::Debug for HashSet<T, S>
where T: Eq + Hash + fmt::Debug,
S: HashState
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "HashSet {{"));
@ -617,10 +610,9 @@ impl<T, S, H> fmt::Debug for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> FromIterator<T> for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<T, S> FromIterator<T> for HashSet<T, S>
where T: Eq + Hash,
S: HashState + Default,
{
fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, S> {
let lower = iter.size_hint().0;
@ -631,10 +623,9 @@ impl<T, S, H> FromIterator<T> for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> Extend<T> for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> Extend<T> for HashSet<T, S>
where T: Eq + Hash,
S: HashState,
{
fn extend<I: Iterator<Item=T>>(&mut self, iter: I) {
for k in iter {
@ -644,10 +635,9 @@ impl<T, S, H> Extend<T> for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> Default for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<T, S> Default for HashSet<T, S>
where T: Eq + Hash,
S: HashState + Default,
{
#[stable(feature = "rust1", since = "1.0.0")]
fn default() -> HashSet<T, S> {
@ -656,10 +646,9 @@ impl<T, S, H> Default for HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash<H> + Clone,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash + Clone,
S: HashState + Default,
{
type Output = HashSet<T, S>;
@ -689,10 +678,9 @@ impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash<H> + Clone,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash + Clone,
S: HashState + Default,
{
type Output = HashSet<T, S>;
@ -722,10 +710,9 @@ impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash<H> + Clone,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash + Clone,
S: HashState + Default,
{
type Output = HashSet<T, S>;
@ -755,10 +742,9 @@ impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash<H> + Clone,
S: HashState<Hasher=H> + Default,
H: hash::Hasher<Output=u64>
impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
where T: Eq + Hash + Clone,
S: HashState + Default,
{
type Output = HashSet<T, S>;
@ -836,10 +822,8 @@ pub struct Union<'a, T: 'a, S: 'a> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
where T: Eq + Hash, S: HashState
{
type Item = &'a T;
type IntoIter = Iter<'a, T>;
@ -850,10 +834,9 @@ impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> IntoIterator for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<T, S> IntoIterator for HashSet<T, S>
where T: Eq + Hash,
S: HashState
{
type Item = T;
type IntoIter = IntoIter<T>;
@ -900,10 +883,8 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, T, S> Iterator for Intersection<'a, T, S>
where T: Eq + Hash, S: HashState
{
type Item = &'a T;
@ -925,10 +906,8 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> Iterator for Difference<'a, T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, T, S> Iterator for Difference<'a, T, S>
where T: Eq + Hash, S: HashState
{
type Item = &'a T;
@ -950,10 +929,8 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
where T: Eq + Hash, S: HashState
{
type Item = &'a T;
@ -962,10 +939,8 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> Iterator for Union<'a, T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
H: hash::Hasher<Output=u64>
impl<'a, T, S> Iterator for Union<'a, T, S>
where T: Eq + Hash, S: HashState
{
type Item = &'a T;

File diff suppressed because it is too large Load Diff

View File

@ -141,6 +141,7 @@ impl SafeHash {
/// 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
/// module to generate a SafeHash.
#[cfg(stage0)]
pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
where T: Hash<H>,
S: HashState<Hasher=H>,
@ -155,6 +156,22 @@ pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
}
/// 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
/// module to generate a SafeHash.
#[cfg(not(stage0))]
pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
where T: Hash, S: HashState
{
let mut state = hash_state.hasher();
t.hash(&mut state);
// We need to avoid 0u64 in order to prevent collisions with
// EMPTY_HASH. We can maintain our precious uniform distribution
// of initial indexes by unconditionally setting the MSB,
// effectively reducing 64-bits hashes to 63 bits.
SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
}
// `replace` casts a `*u64` to a `*SafeHash`. Since we statically
// ensure that a `FullBucket` points to an index with a non-zero hash,
// and a `SafeHash` is just a `u64` with a different name, this is

View File

@ -40,7 +40,8 @@ use mem;
use string::{String, CowString};
use ops;
use cmp;
use hash::{Hash, Hasher, Writer};
use hash::{Hash, Hasher};
#[cfg(stage0)] use hash::Writer;
use old_path::{Path, GenericPath};
use sys::os_str::{Buf, Slice};
@ -162,12 +163,21 @@ impl Ord for OsString {
}
}
#[cfg(stage0)]
impl<'a, S: Hasher + Writer> Hash<S> for OsString {
#[inline]
fn hash(&self, state: &mut S) {
(&**self).hash(state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsString {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(&**self).hash(state)
}
}
impl OsStr {
/// Coerce directly from a `&str` slice to a `&OsStr` slice.
@ -253,12 +263,21 @@ impl Ord for OsStr {
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
}
#[cfg(stage0)]
impl<'a, S: Hasher + Writer> Hash<S> for OsStr {
#[inline]
fn hash(&self, state: &mut S) {
self.bytes().hash(state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsStr {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.bytes().hash(state)
}
}
impl Debug for OsStr {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {

View File

@ -147,6 +147,7 @@ impl PartialEq for Repr {
}
impl Eq for Repr {}
#[cfg(stage0)]
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Repr {
fn hash(&self, s: &mut S) {
match *self {
@ -160,6 +161,21 @@ impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Repr {
}
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Repr {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
match *self {
Repr::V4(ref a) => {
(a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s)
}
Repr::V6(ref a) => {
(a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr,
a.sin6_flowinfo, a.sin6_scope_id).hash(s)
}
}
}
}
/// A trait for objects which can be converted or resolved to one or more
/// `SocketAddr` values.

View File

@ -189,11 +189,19 @@ impl PartialEq for Ipv4Addr {
}
impl Eq for Ipv4Addr {}
#[cfg(stage0)]
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv4Addr {
fn hash(&self, s: &mut S) {
self.inner.s_addr.hash(s)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Ipv4Addr {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
self.inner.s_addr.hash(s)
}
}
impl PartialOrd for Ipv4Addr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
@ -421,11 +429,19 @@ impl PartialEq for Ipv6Addr {
}
impl Eq for Ipv6Addr {}
#[cfg(stage0)]
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv6Addr {
fn hash(&self, s: &mut S) {
self.inner.s6_addr.hash(s)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Ipv6Addr {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
self.inner.s6_addr.hash(s)
}
}
impl PartialOrd for Ipv6Addr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {

View File

@ -100,12 +100,21 @@ impl FromStr for Path {
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct ParsePathError;
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {
self.repr.hash(state)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Path {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.repr.hash(state)
}
}
impl BytesContainer for Path {
#[inline]

View File

@ -127,6 +127,7 @@ impl FromStr for Path {
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct ParsePathError;
#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
@ -140,6 +141,21 @@ impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
// No-op because the `hash` implementation will be wrong.
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Path {
#[cfg(not(test))]
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.repr.hash(state)
}
#[cfg(test)]
#[inline]
fn hash<H: hash::Hasher>(&self, _: &mut H) {
// No-op because the `hash` implementation will be wrong.
}
}
impl BytesContainer for Path {
#[inline]

View File

@ -31,7 +31,8 @@ use ascii::*;
use borrow::Cow;
use cmp;
use fmt;
use hash::{Hash, Writer, Hasher};
use hash::{Hash, Hasher};
#[cfg(stage0)] use hash::Writer;
use iter::FromIterator;
use mem;
use num::Int;
@ -794,13 +795,22 @@ impl<'a> Iterator for EncodeWide<'a> {
}
}
#[cfg(stage0)]
impl<S: Writer + Hasher> Hash<S> for CodePoint {
#[inline]
fn hash(&self, state: &mut S) {
self.value.hash(state)
}
}
#[cfg(not(stage0))]
impl Hash for CodePoint {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state)
}
}
#[cfg(stage0)]
impl<S: Writer + Hasher> Hash<S> for Wtf8Buf {
#[inline]
fn hash(&self, state: &mut S) {
@ -808,7 +818,16 @@ impl<S: Writer + Hasher> Hash<S> for Wtf8Buf {
0xfeu8.hash(state)
}
}
#[cfg(not(stage0))]
impl Hash for Wtf8Buf {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.bytes);
0xfeu8.hash(state)
}
}
#[cfg(stage0)]
impl<'a, S: Writer + Hasher> Hash<S> for Wtf8 {
#[inline]
fn hash(&self, state: &mut S) {
@ -816,6 +835,14 @@ impl<'a, S: Writer + Hasher> Hash<S> for Wtf8 {
0xfeu8.hash(state)
}
}
#[cfg(not(stage0))]
impl Hash for Wtf8 {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.bytes);
0xfeu8.hash(state)
}
}
impl AsciiExt for Wtf8 {
type Owned = Wtf8Buf;

View File

@ -12,6 +12,7 @@ use prelude::v1::*;
use self::Req::*;
use collections::HashMap;
#[cfg(stage0)]
use collections::hash_map::Hasher;
use ffi::CString;
use hash::Hash;
@ -63,6 +64,7 @@ impl Process {
mkerr_libc(r)
}
#[cfg(stage0)]
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
out_fd: Option<P>, err_fd: Option<P>)
-> IoResult<Process>
@ -278,6 +280,214 @@ impl Process {
})
})
}
#[cfg(not(stage0))]
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
out_fd: Option<P>, err_fd: Option<P>)
-> IoResult<Process>
where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
K: BytesContainer + Eq + Hash, V: BytesContainer
{
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
use libc::funcs::bsd44::getdtablesize;
mod rustrt {
extern {
pub fn rust_unset_sigprocmask();
}
}
unsafe fn set_cloexec(fd: c_int) {
let ret = c::ioctl(fd, c::FIOCLEX);
assert_eq!(ret, 0);
}
let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
// temporary until unboxed closures land
let cfg = unsafe {
mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
};
with_envp(cfg.env(), move|envp: *const c_void| {
with_argv(cfg.program(), cfg.args(), move|argv: *const *const libc::c_char| unsafe {
let (input, mut output) = try!(sys::os::pipe());
// We may use this in the child, so perform allocations before the
// fork
let devnull = b"/dev/null\0";
set_cloexec(output.fd());
let pid = fork();
if pid < 0 {
return Err(super::last_error())
} else if pid > 0 {
#[inline]
fn combine(arr: &[u8]) -> i32 {
let a = arr[0] as u32;
let b = arr[1] as u32;
let c = arr[2] as u32;
let d = arr[3] as u32;
((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
}
let p = Process{ pid: pid };
drop(output);
let mut bytes = [0; 8];
return match input.read(&mut bytes) {
Ok(8) => {
assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
"Validation on the CLOEXEC pipe failed: {:?}", bytes);
let errno = combine(&bytes[0.. 4]);
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
Err(super::decode_error(errno))
}
Err(ref e) if e.kind == EndOfFile => Ok(p),
Err(e) => {
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
panic!("the CLOEXEC pipe failed: {:?}", e)
},
Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
panic!("short read on the CLOEXEC pipe")
}
};
}
// And at this point we've reached a special time in the life of the
// child. The child must now be considered hamstrung and unable to
// do anything other than syscalls really. Consider the following
// scenario:
//
// 1. Thread A of process 1 grabs the malloc() mutex
// 2. Thread B of process 1 forks(), creating thread C
// 3. Thread C of process 2 then attempts to malloc()
// 4. The memory of process 2 is the same as the memory of
// process 1, so the mutex is locked.
//
// This situation looks a lot like deadlock, right? It turns out
// that this is what pthread_atfork() takes care of, which is
// presumably implemented across platforms. The first thing that
// threads to *before* forking is to do things like grab the malloc
// mutex, and then after the fork they unlock it.
//
// Despite this information, libnative's spawn has been witnessed to
// deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
// all collected backtraces point at malloc/free traffic in the
// child spawned process.
//
// For this reason, the block of code below should contain 0
// invocations of either malloc of free (or their related friends).
//
// As an example of not having malloc/free traffic, we don't close
// this file descriptor by dropping the FileDesc (which contains an
// allocation). Instead we just close it manually. This will never
// have the drop glue anyway because this code never returns (the
// child will either exec() or invoke libc::exit)
let _ = libc::close(input.fd());
fn fail(output: &mut FileDesc) -> ! {
let errno = sys::os::errno() as u32;
let bytes = [
(errno >> 24) as u8,
(errno >> 16) as u8,
(errno >> 8) as u8,
(errno >> 0) as u8,
CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
];
// pipe I/O up to PIPE_BUF bytes should be atomic
assert!(output.write(&bytes).is_ok());
unsafe { libc::_exit(1) }
}
rustrt::rust_unset_sigprocmask();
// If a stdio file descriptor is set to be ignored (via a -1 file
// descriptor), then we don't actually close it, but rather open
// up /dev/null into that file descriptor. Otherwise, the first file
// descriptor opened up in the child would be numbered as one of the
// stdio file descriptors, which is likely to wreak havoc.
let setup = |src: Option<P>, dst: c_int| {
let src = match src {
None => {
let flags = if dst == libc::STDIN_FILENO {
libc::O_RDONLY
} else {
libc::O_RDWR
};
libc::open(devnull.as_ptr() as *const _, flags, 0)
}
Some(obj) => {
let fd = obj.as_inner().fd();
// Leak the memory and the file descriptor. We're in the
// child now an all our resources are going to be
// cleaned up very soon
mem::forget(obj);
fd
}
};
src != -1 && retry(|| dup2(src, dst)) != -1
};
if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) }
if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) }
// close all other fds
for fd in (3..getdtablesize()).rev() {
if fd != output.fd() {
let _ = close(fd as c_int);
}
}
match cfg.gid() {
Some(u) => {
if libc::setgid(u as libc::gid_t) != 0 {
fail(&mut output);
}
}
None => {}
}
match cfg.uid() {
Some(u) => {
// When dropping privileges from root, the `setgroups` call
// will remove any extraneous groups. If we don't call this,
// then even though our uid has dropped, we may still have
// groups that enable us to do super-user things. This will
// fail if we aren't root, so don't bother checking the
// return value, this is just done as an optimistic
// privilege dropping function.
extern {
fn setgroups(ngroups: libc::c_int,
ptr: *const libc::c_void) -> libc::c_int;
}
let _ = setgroups(0, ptr::null());
if libc::setuid(u as libc::uid_t) != 0 {
fail(&mut output);
}
}
None => {}
}
if cfg.detach() {
// Don't check the error of setsid because it fails if we're the
// process leader already. We just forked so it shouldn't return
// error, but ignore it anyway.
let _ = libc::setsid();
}
if !dirp.is_null() && chdir(dirp) == -1 {
fail(&mut output);
}
if !envp.is_null() {
*sys::os::environ() = envp as *const _;
}
let _ = execvp(*argv, argv as *mut _);
fail(&mut output);
})
})
}
pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
use cmp;
@ -556,6 +766,7 @@ fn with_argv<T,F>(prog: &CString, args: &[CString],
cb(ptrs.as_ptr())
}
#[cfg(stage0)]
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
cb: F)
-> T
@ -593,6 +804,44 @@ fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
_ => cb(ptr::null())
}
}
#[cfg(not(stage0))]
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
cb: F)
-> T
where F : FnOnce(*const c_void) -> T,
K : BytesContainer + Eq + Hash,
V : BytesContainer
{
// On posixy systems we can pass a char** for envp, which is a
// null-terminated array of "k=v\0" strings. Since we must create
// these strings locally, yet expose a raw pointer to them, we
// create a temporary vector to own the CStrings that outlives the
// call to cb.
match env {
Some(env) => {
let mut tmps = Vec::with_capacity(env.len());
for pair in env {
let mut kv = Vec::new();
kv.push_all(pair.0.container_as_bytes());
kv.push('=' as u8);
kv.push_all(pair.1.container_as_bytes());
kv.push(0); // terminating null
tmps.push(kv);
}
// As with `with_argv`, this is unsafe, since cb could leak the pointers.
let mut ptrs: Vec<*const libc::c_char> =
tmps.iter()
.map(|tmp| tmp.as_ptr() as *const libc::c_char)
.collect();
ptrs.push(ptr::null());
cb(ptrs.as_ptr() as *const c_void)
}
_ => cb(ptr::null())
}
}
fn translate_status(status: c_int) -> ProcessExit {
#![allow(non_snake_case)]

View File

@ -11,7 +11,6 @@
use prelude::v1::*;
use collections::HashMap;
use collections::hash_map::Hasher;
use env;
use ffi::{OsString, OsStr, CString};
use fmt;

View File

@ -14,7 +14,6 @@ use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ext::deriving::generic::*;
use ext::deriving::generic::ty::*;
use parse::token::InternedString;
use ptr::P;
pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
@ -26,30 +25,26 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
{
let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
vec!(box Literal(Path::new_local("__S"))), true);
let generics = LifetimeBounds {
lifetimes: Vec::new(),
bounds: vec!(("__S",
vec!(path_std!(cx, core::hash::Writer),
path_std!(cx, core::hash::Hasher)))),
};
let args = Path::new_local("__S");
let inline = cx.meta_word(span, InternedString::new("inline"));
let attrs = vec!(cx.attribute(span, inline));
vec!(), true);
let arg = Path::new_local("__H");
let hash_trait_def = TraitDef {
span: span,
attributes: Vec::new(),
path: path,
additional_bounds: Vec::new(),
generics: generics,
generics: LifetimeBounds::empty(),
methods: vec!(
MethodDef {
name: "hash",
generics: LifetimeBounds::empty(),
generics: LifetimeBounds {
lifetimes: Vec::new(),
bounds: vec![("__H",
vec![path_std!(cx, core::hash::Hasher)])],
},
explicit_self: borrowed_explicit_self(),
args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
args: vec!(Ptr(box Literal(arg), Borrowed(None, MutMutable))),
ret_ty: nil_ty(),
attributes: attrs,
attributes: vec![],
combine_substructure: combine_substructure(box |a, b, c| {
hash_substructure(a, b, c)
})

View File

@ -28,7 +28,6 @@
#![feature(collections)]
#![feature(core)]
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(libc)]

View File

@ -111,11 +111,18 @@ impl<T: Display> Display for P<T> {
}
}
#[cfg(stage0)]
impl<S: Hasher, T: Hash<S>> Hash<S> for P<T> {
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
impl<T: Hash> Hash for P<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: 'static + Decodable> Decodable for P<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {

View File

@ -18,9 +18,9 @@ use std::borrow::BorrowFrom;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::HashMap;
#[cfg(stage0)] use std::collections::hash_map::Hasher;
use std::fmt;
use std::hash::Hash;
use std::collections::hash_map::Hasher;
use std::ops::Deref;
use std::rc::Rc;
@ -30,6 +30,7 @@ pub struct Interner<T> {
}
// when traits can extend traits, we should extend index<Name,T> to get []
#[cfg(stage0)]
impl<T: Eq + Hash<Hasher> + Clone + 'static> Interner<T> {
pub fn new() -> Interner<T> {
Interner {
@ -92,6 +93,70 @@ impl<T: Eq + Hash<Hasher> + Clone + 'static> Interner<T> {
*self.vect.borrow_mut() = Vec::new();
}
}
// when traits can extend traits, we should extend index<Name,T> to get []
#[cfg(not(stage0))]
impl<T: Eq + Hash + Clone + 'static> Interner<T> {
pub fn new() -> Interner<T> {
Interner {
map: RefCell::new(HashMap::new()),
vect: RefCell::new(Vec::new()),
}
}
pub fn prefill(init: &[T]) -> Interner<T> {
let rv = Interner::new();
for v in init {
rv.intern((*v).clone());
}
rv
}
pub fn intern(&self, val: T) -> Name {
let mut map = self.map.borrow_mut();
match (*map).get(&val) {
Some(&idx) => return idx,
None => (),
}
let mut vect = self.vect.borrow_mut();
let new_idx = Name((*vect).len() as u32);
(*map).insert(val.clone(), new_idx);
(*vect).push(val);
new_idx
}
pub fn gensym(&self, val: T) -> Name {
let mut vect = self.vect.borrow_mut();
let new_idx = Name((*vect).len() as u32);
// leave out of .map to avoid colliding
(*vect).push(val);
new_idx
}
pub fn get(&self, idx: Name) -> T {
let vect = self.vect.borrow();
(*vect)[idx.usize()].clone()
}
pub fn len(&self) -> usize {
let vect = self.vect.borrow();
(*vect).len()
}
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<T> + Eq + Hash {
let map = self.map.borrow();
match (*map).get(val) {
Some(v) => Some(*v),
None => None,
}
}
pub fn clear(&self) {
*self.map.borrow_mut() = HashMap::new();
*self.vect.borrow_mut() = Vec::new();
}
}
#[derive(Clone, PartialEq, Hash, PartialOrd)]
pub struct RcStr {
@ -210,6 +275,7 @@ impl StrInterner {
self.vect.borrow().len()
}
#[cfg(stage0)]
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<RcStr> + Eq + Hash<Hasher> {
match (*self.map.borrow()).get(val) {
@ -217,6 +283,14 @@ impl StrInterner {
None => None,
}
}
#[cfg(not(stage0))]
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<RcStr> + Eq + Hash {
match (*self.map.borrow()).get(val) {
Some(v) => Some(*v),
None => None,
}
}
pub fn clear(&self) {
*self.map.borrow_mut() = HashMap::new();

View File

@ -37,7 +37,6 @@
#![feature(collections)]
#![feature(core)]
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(old_path)]

View File

@ -12,7 +12,7 @@
use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_map::{self, Hasher};
use std::collections::hash_map;
use std::hash::Hash;
use std::mem;
use std::num::{Float, FromPrimitive};
@ -333,7 +333,7 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
/// Returns a HashMap with the number of occurrences of every element in the
/// sequence that the iterator exposes.
pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
where T: Iterator<Item=U>, U: Eq + Clone + Hash<Hasher>
where T: Iterator<Item=U>, U: Eq + Clone + Hash
{
let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
for elem in iter {

View File

@ -18,7 +18,6 @@ extern crate rand;
use std::collections::BTreeSet;
use std::collections::BitvSet;
use std::collections::HashSet;
use std::collections::hash_map::Hasher;
use std::hash::Hash;
use std::env;
use std::time::Duration;
@ -43,7 +42,7 @@ trait MutableSet<T> {
fn contains(&self, k: &T) -> bool;
}
impl<T: Hash<Hasher> + Eq> MutableSet<T> for HashSet<T> {
impl<T: Hash + Eq> MutableSet<T> for HashSet<T> {
fn insert(&mut self, k: T) { self.insert(k); }
fn remove(&mut self, k: &T) -> bool { self.remove(k) }
fn contains(&self, k: &T) -> bool { self.contains(k) }

View File

@ -16,6 +16,6 @@ impl Bar {
#[derive(Hash)]
struct Foo(Bar);
//~^ error: the trait `core::hash::Hash<_>` is not implemented for the type `Bar`
//~^ error: the trait `core::hash::Hash` is not implemented for the type `Bar`
fn main() {}

View File

@ -17,7 +17,7 @@ struct Person {
phone: uint,
}
fn hash<T: Hash<SipHasher>>(t: &T) -> u64 {
fn hash<T: Hash>(t: &T) -> u64 {
std::hash::hash::<T, SipHasher>(t)
}

View File

@ -20,7 +20,7 @@ struct Foo {
baz: int
}
fn hash<T: Hash<SipHasher>>(_t: &T) {}
fn hash<T: Hash>(_t: &T) {}
pub fn main() {
let a = Foo {bar: 4, baz: -3};

View File

@ -17,7 +17,7 @@ struct Foo {
baz: int
}
fn hash<T: Hash<SipHasher>>(_t: &T) {}
fn hash<T: Hash>(_t: &T) {}
pub fn main() {
let a = Foo {bar: 4, baz: -3};