From eb8f43cc25d21b8b987553ad50c601ded28e1d33 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 21 Jan 2016 10:28:39 -0800
Subject: [PATCH 1/2] std: Stabilize custom hasher support in HashMap

This commit implements the stabilization of the custom hasher support intended
for 1.7 but left out due to some last-minute questions that needed some
decisions. A summary of the actions done in this PR are:

Stable

* `std::hash::BuildHasher`
* `BuildHasher::Hasher`
* `BuildHasher::build_hasher`
* `std::hash::BuildHasherDefault`
* `HashMap::with_hasher`
* `HashMap::with_capacity_and_hasher`
* `HashSet::with_hasher`
* `HashSet::with_capacity_and_hasher`
* `std::collections::hash_map::RandomState`
* `RandomState::new`

Deprecated

* `std::collections::hash_state`
* `std::collections::hash_state::HashState` - this trait was also moved into
  `std::hash` with a reexport here to ensure that we can have a blanket impl to
  prevent immediate breakage on nightly. Note that this is unstable in both
  location.
* `HashMap::with_hash_state` - renamed
* `HashMap::with_capacity_and_hash_state` - renamed
* `HashSet::with_hash_state` - renamed
* `HashSet::with_capacity_and_hash_state` - renamed

Closes #27713
---
 src/libcore/hash/mod.rs              |  72 ++++++++++++++++
 src/librustc/lib.rs                  |   1 -
 src/librustc/util/common.rs          |   5 +-
 src/librustc_data_structures/fnv.rs  |  11 ++-
 src/librustc_data_structures/lib.rs  |   1 -
 src/libserialize/collection_impls.rs |  15 ++--
 src/libserialize/lib.rs              |   1 -
 src/libstd/collections/hash/map.rs   | 124 ++++++++++++++-------------
 src/libstd/collections/hash/set.rs   |  95 +++++++++++---------
 src/libstd/collections/hash/state.rs |  22 +----
 src/libstd/collections/hash/table.rs |   7 +-
 src/libstd/collections/mod.rs        |   2 +
 src/libstd/lib.rs                    |   1 +
 13 files changed, 215 insertions(+), 142 deletions(-)

diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 0781dd3b7742f..9ab55620e0aec 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -73,6 +73,7 @@
 
 use prelude::v1::*;
 
+use marker;
 use mem;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -190,6 +191,77 @@ pub trait Hasher {
     }
 }
 
+/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
+/// which a `HashMap` can then use to hash keys independently.
+///
+/// Note that for each instance of `BuildHasher` the create hashers should be
+/// identical. That is if the same stream of bytes is fed into each hasher the
+/// same output will also be generated.
+#[stable(since = "1.7.0", feature = "build_hasher")]
+pub trait BuildHasher {
+    /// Type of the hasher that will be created.
+    #[stable(since = "1.7.0", feature = "build_hasher")]
+    type Hasher: Hasher;
+
+    /// Creates a new hasher.
+    #[stable(since = "1.7.0", feature = "build_hasher")]
+    fn build_hasher(&self) -> Self::Hasher;
+}
+
+/// A structure which implements `BuildHasher` for all `Hasher` types which also
+/// implement `Default`.
+///
+/// This struct is 0-sized and does not need construction.
+#[stable(since = "1.7.0", feature = "build_hasher")]
+pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> {
+    type Hasher = H;
+
+    fn build_hasher(&self) -> H {
+        H::default()
+    }
+}
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H> Clone for BuildHasherDefault<H> {
+    fn clone(&self) -> BuildHasherDefault<H> {
+        BuildHasherDefault(marker::PhantomData)
+    }
+}
+
+#[stable(since = "1.7.0", feature = "build_hasher")]
+impl<H> Default for BuildHasherDefault<H> {
+    fn default() -> BuildHasherDefault<H> {
+        BuildHasherDefault(marker::PhantomData)
+    }
+}
+
+// The HashState trait is super deprecated, but it's here to have the blanket
+// impl that goes from HashState -> BuildHasher
+
+/// Deprecated, renamed to `BuildHasher`
+#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+           issue = "27713")]
+#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash and \
+                                              renamed to BuildHasher")]
+pub trait HashState {
+    /// Type of the hasher that will be created.
+    type Hasher: Hasher;
+
+    /// Creates a new hasher based on the given state of this object.
+    fn hasher(&self) -> Self::Hasher;
+}
+
+#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+           issue = "27713")]
+#[allow(deprecated)]
+impl<T: HashState> BuildHasher for T {
+    type Hasher = T::Hasher;
+    fn build_hasher(&self) -> T::Hasher { self.hasher() }
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 mod impls {
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 501a03f128664..2712ed2a19038 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,7 +29,6 @@
 #![feature(collections)]
 #![feature(const_fn)]
 #![feature(enumset)]
-#![feature(hashmap_hasher)]
 #![feature(iter_arith)]
 #![feature(libc)]
 #![feature(nonzero)]
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 2481cab78b4d6..9441e34cb9b1f 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -12,10 +12,9 @@
 
 use std::cell::{RefCell, Cell};
 use std::collections::HashMap;
-use std::collections::hash_state::HashState;
 use std::ffi::CString;
 use std::fmt::Debug;
-use std::hash::Hash;
+use std::hash::{Hash, BuildHasher};
 use std::iter::repeat;
 use std::path::Path;
 use std::time::Instant;
@@ -217,7 +216,7 @@ pub trait MemoizationMap {
 }
 
 impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
-    where K: Hash+Eq+Clone, V: Clone, S: HashState
+    where K: Hash+Eq+Clone, V: Clone, S: BuildHasher
 {
     type Key = K;
     type Value = V;
diff --git a/src/librustc_data_structures/fnv.rs b/src/librustc_data_structures/fnv.rs
index 77baa84c0236d..6f4dc28e12221 100644
--- a/src/librustc_data_structures/fnv.rs
+++ b/src/librustc_data_structures/fnv.rs
@@ -9,21 +9,20 @@
 // except according to those terms.
 
 use std::collections::{HashMap, HashSet};
-use std::collections::hash_state::DefaultState;
 use std::default::Default;
-use std::hash::{Hasher, Hash};
+use std::hash::{Hasher, Hash, BuildHasherDefault};
 
-pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
-pub type FnvHashSet<V> = HashSet<V, DefaultState<FnvHasher>>;
+pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FnvHasher>>;
+pub type FnvHashSet<V> = HashSet<V, BuildHasherDefault<FnvHasher>>;
 
 #[allow(non_snake_case)]
 pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
-    Default::default()
+    HashMap::default()
 }
 
 #[allow(non_snake_case)]
 pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
-    Default::default()
+    HashSet::default()
 }
 
 /// A speedy hash algorithm for node ids and def ids. The hashmap in
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 1fbbdf17455b2..20caf7dd0cfc1 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -24,7 +24,6 @@
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![feature(hashmap_hasher)]
 #![feature(nonzero)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs
index e21307cc75292..804e1af19aba2 100644
--- a/src/libserialize/collection_impls.rs
+++ b/src/libserialize/collection_impls.rs
@@ -10,8 +10,7 @@
 
 //! Implementations of serialization for structures found in libcollections
 
-use std::hash::Hash;
-use std::collections::hash_state::HashState;
+use std::hash::{Hash, BuildHasher};
 use std::mem;
 
 use {Decodable, Encodable, Decoder, Encoder};
@@ -159,7 +158,7 @@ impl<
 impl<K, V, S> Encodable for HashMap<K, V, S>
     where K: Encodable + Hash + Eq,
           V: Encodable,
-          S: HashState,
+          S: BuildHasher,
 {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
@@ -177,12 +176,12 @@ impl<K, V, S> Encodable for HashMap<K, V, S>
 impl<K, V, S> Decodable for HashMap<K, V, S>
     where K: Decodable + Hash + Eq,
           V: Decodable,
-          S: HashState + Default,
+          S: BuildHasher + 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);
+            let mut map = HashMap::with_capacity_and_hasher(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)));
@@ -195,7 +194,7 @@ impl<K, V, S> Decodable for HashMap<K, V, S>
 
 impl<T, S> Encodable for HashSet<T, S>
     where T: Encodable + Hash + Eq,
-          S: HashState,
+          S: BuildHasher,
 {
     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
@@ -211,12 +210,12 @@ impl<T, S> Encodable for HashSet<T, S>
 
 impl<T, S> Decodable for HashSet<T, S>
     where T: Decodable + Hash + Eq,
-          S: HashState + Default,
+          S: BuildHasher + 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);
+            let mut set = HashSet::with_capacity_and_hasher(len, state);
             for i in 0..len {
                 set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index 910600d91e456..8bb596c8bb248 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -29,7 +29,6 @@ Core encoding and decoding interfaces.
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(enumset)]
-#![feature(hashmap_hasher)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_char)]
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index e43101b7c9d0d..509964cd29b88 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -13,16 +13,12 @@ use self::SearchResult::*;
 use self::VacantEntryState::*;
 
 use borrow::Borrow;
-use clone::Clone;
-use cmp::{max, Eq, PartialEq};
-use default::Default;
+use cmp::max;
 use fmt::{self, Debug};
-use hash::{Hash, SipHasher};
-use iter::{self, Iterator, ExactSizeIterator, IntoIterator, FromIterator, Extend, Map};
-use marker::Sized;
+use hash::{Hash, SipHasher, BuildHasher};
+use iter::{self, Map, FromIterator};
 use mem::{self, replace};
-use ops::{Deref, FnMut, FnOnce, Index};
-use option::Option::{self, Some, None};
+use ops::{Deref, Index};
 use rand::{self, Rng};
 
 use super::table::{
@@ -39,7 +35,6 @@ use super::table::BucketState::{
     Empty,
     Full,
 };
-use super::state::HashState;
 
 const INITIAL_LOG2_CAP: usize = 5;
 const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
@@ -307,7 +302,7 @@ fn test_resize_policy() {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashMap<K, V, S = RandomState> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
-    hash_state: S,
+    hash_builder: S,
 
     table: RawTable<K, V>,
 
@@ -455,10 +450,10 @@ impl<K, V, M> SearchResult<K, V, M> {
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash {
-        table::make_hash(&self.hash_state, x)
+        table::make_hash(&self.hash_builder, x)
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
@@ -528,40 +523,52 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(capacity: usize) -> HashMap<K, V, RandomState> {
-        HashMap::with_capacity_and_hash_state(capacity, Default::default())
+        HashMap::with_capacity_and_hasher(capacity, Default::default())
     }
 }
 
 impl<K, V, S> HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
-    /// Creates an empty hashmap which will use the given hasher to hash keys.
+    /// Creates an empty hashmap which will use the given hash builder to hash
+    /// keys.
     ///
     /// The created map has the default initial capacity.
     ///
+    /// Warning: `hash_builder` is normally randomly generated, and
+    /// is designed to allow HashMaps to be resistant to attacks that
+    /// cause many collisions and very poor performance. Setting it
+    /// manually using this function can expose a DoS attack vector.
+    ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut map = HashMap::with_hash_state(s);
+    /// let mut map = HashMap::with_hasher(s);
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap {
-            hash_state:    hash_state,
+            hash_builder: hash_builder,
             resize_policy: DefaultResizePolicy::new(),
-            table:         RawTable::new(0),
+            table: RawTable::new(0),
         }
     }
 
+    /// Deprecated, renamed to `with_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
+    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
+        HashMap::with_hasher(hash_state)
+    }
+
     /// Creates an empty HashMap with space for at least `capacity`
     /// elements, using `hasher` to hash the keys.
     ///
@@ -573,31 +580,39 @@ impl<K, V, S> HashMap<K, V, S>
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashMap;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut map = HashMap::with_capacity_and_hash_state(10, s);
+    /// let mut map = HashMap::with_capacity_and_hasher(10, s);
     /// map.insert(1, 2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
-                                        -> HashMap<K, V, S> {
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S)
+                                    -> HashMap<K, V, S> {
         let resize_policy = DefaultResizePolicy::new();
         let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
         let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
         assert!(internal_cap >= capacity, "capacity overflow");
         HashMap {
-            hash_state:    hash_state,
+            hash_builder: hash_builder,
             resize_policy: resize_policy,
-            table:         RawTable::new(internal_cap),
+            table: RawTable::new(internal_cap),
         }
     }
 
+    /// Deprecated, renamed to `with_capacity_and_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0",
+                       reason = "renamed to with_capacity_and_hasher")]
+    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
+                                        -> HashMap<K, V, S> {
+        HashMap::with_capacity_and_hasher(capacity, hash_state)
+    }
+
     /// Returns the number of elements the map can hold without reallocating.
     ///
     /// This number is a lower bound; the `HashMap<K, V>` might be able to hold
@@ -1212,7 +1227,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
-    where K: Eq + Hash, V: PartialEq, S: HashState
+    where K: Eq + Hash, V: PartialEq, S: BuildHasher
 {
     fn eq(&self, other: &HashMap<K, V, S>) -> bool {
         if self.len() != other.len() { return false; }
@@ -1225,12 +1240,12 @@ impl<K, V, S> PartialEq for HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Eq for HashMap<K, V, S>
-    where K: Eq + Hash, V: Eq, S: HashState
+    where K: Eq + Hash, V: Eq, S: BuildHasher
 {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Debug for HashMap<K, V, S>
-    where K: Eq + Hash + Debug, V: Debug, S: HashState
+    where K: Eq + Hash + Debug, V: Debug, S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_map().entries(self.iter()).finish()
@@ -1240,10 +1255,10 @@ impl<K, V, S> Debug for HashMap<K, V, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Default for HashMap<K, V, S>
     where K: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn default() -> HashMap<K, V, S> {
-        HashMap::with_hash_state(Default::default())
+        HashMap::with_hasher(Default::default())
     }
 }
 
@@ -1251,7 +1266,7 @@ impl<K, V, S> Default for HashMap<K, V, S>
 impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
     where K: Eq + Hash + Borrow<Q>,
           Q: Eq + Hash,
-          S: HashState,
+          S: BuildHasher,
 {
     type Output = V;
 
@@ -1368,7 +1383,7 @@ enum VacantEntryState<K, V, M> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (&'a K, &'a V);
     type IntoIter = Iter<'a, K, V>;
@@ -1380,7 +1395,7 @@ impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (&'a K, &'a mut V);
     type IntoIter = IterMut<'a, K, V>;
@@ -1392,7 +1407,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> IntoIterator for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     type Item = (K, V);
     type IntoIter = IntoIter<K, V>;
@@ -1571,13 +1586,12 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState + Default
+    where K: Eq + Hash, S: BuildHasher + Default
 {
     fn from_iter<T: IntoIterator<Item=(K, V)>>(iterable: T) -> HashMap<K, V, S> {
         let iter = iterable.into_iter();
         let lower = iter.size_hint().0;
-        let mut map = HashMap::with_capacity_and_hash_state(lower,
-                                                            Default::default());
+        let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
         map.extend(iter);
         map
     }
@@ -1585,7 +1599,7 @@ impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash, S: HashState
+    where K: Eq + Hash, S: BuildHasher
 {
     fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
         for (k, v) in iter {
@@ -1596,7 +1610,7 @@ impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-    where K: Eq + Hash + Copy, V: Copy, S: HashState
+    where K: Eq + Hash + Copy, V: Copy, S: BuildHasher
 {
     fn extend<T: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: T) {
         self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
@@ -1609,34 +1623,28 @@ impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
 /// `Hasher`, but the hashers created by two different `RandomState`
 /// instances are unlikely to produce the same result for the same values.
 #[derive(Clone)]
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
+#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
 pub struct RandomState {
     k0: u64,
     k1: u64,
 }
 
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
 impl RandomState {
     /// Constructs a new `RandomState` that is initialized with random keys.
     #[inline]
     #[allow(deprecated)] // rand
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn new() -> RandomState {
         let mut r = rand::thread_rng();
         RandomState { k0: r.gen(), k1: r.gen() }
     }
 }
 
-#[unstable(feature = "hashmap_hasher",
-           reason = "hashing an hash maps may be altered",
-           issue = "27713")]
-impl HashState for RandomState {
+#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+impl BuildHasher for RandomState {
     type Hasher = SipHasher;
     #[inline]
-    fn hasher(&self) -> SipHasher {
+    fn build_hasher(&self) -> SipHasher {
         SipHasher::new_with_keys(self.k0, self.k1)
     }
 }
@@ -1650,7 +1658,7 @@ impl Default for RandomState {
 }
 
 impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
-    where K: Eq + Hash + Borrow<Q>, S: HashState, Q: Eq + Hash
+    where K: Eq + Hash + Borrow<Q>, S: BuildHasher, Q: Eq + Hash
 {
     type Key = K;
 
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 761709d41e77c..b5f47853afd4e 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -9,19 +9,13 @@
 // except according to those terms.
 
 use borrow::Borrow;
-use clone::Clone;
-use cmp::{Eq, PartialEq};
-use core::marker::Sized;
-use default::Default;
 use fmt;
-use hash::Hash;
-use iter::{Iterator, IntoIterator, ExactSizeIterator, FromIterator, Map, Chain, Extend};
+use hash::{Hash, BuildHasher};
+use iter::{Map, Chain, FromIterator};
 use ops::{BitOr, BitAnd, BitXor, Sub};
-use option::Option::{Some, None, self};
 
 use super::Recover;
 use super::map::{self, HashMap, Keys, RandomState};
-use super::state::HashState;
 
 const INITIAL_CAPACITY: usize = 32;
 
@@ -144,30 +138,32 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
 }
 
 impl<T, S> HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     /// Creates a new empty hash set which will use the given hasher to hash
     /// keys.
     ///
     /// The hash set is also created with the default initial capacity.
     ///
+    /// Warning: `hasher` is normally randomly generated, and
+    /// is designed to allow `HashSet`s to be resistant to attacks that
+    /// cause many collisions and very poor performance. Setting it
+    /// manually using this function can expose a DoS attack vector.
+    ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut set = HashSet::with_hash_state(s);
+    /// let mut set = HashSet::with_hasher(s);
     /// set.insert(2);
     /// ```
     #[inline]
-    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
-               issue = "27713")]
-    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
-        HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_hasher(hasher: S) -> HashSet<T, S> {
+        HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
 
     /// Creates an empty HashSet with space for at least `capacity`
@@ -181,23 +177,40 @@ impl<T, S> HashSet<T, S>
     /// # Examples
     ///
     /// ```
-    /// #![feature(hashmap_hasher)]
-    ///
     /// use std::collections::HashSet;
     /// use std::collections::hash_map::RandomState;
     ///
     /// let s = RandomState::new();
-    /// let mut set = HashSet::with_capacity_and_hash_state(10, s);
+    /// let mut set = HashSet::with_capacity_and_hasher(10, s);
     /// set.insert(1);
     /// ```
     #[inline]
+    #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
+    pub fn with_capacity_and_hasher(capacity: usize, hasher: S)
+                                    -> HashSet<T, S> {
+        HashSet {
+            map: HashMap::with_capacity_and_hasher(capacity, hasher),
+        }
+    }
+
+    /// Deprecated, renamed to `with_hasher`
+    #[inline]
     #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
                issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
+    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
+        HashSet::with_hasher(hash_state)
+    }
+
+    /// Deprecated, renamed to `with_capacity_and_hasher`
+    #[inline]
+    #[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
+               issue = "27713")]
+    #[rustc_deprecated(since = "1.7.0",
+                       reason = "renamed to with_capacity_and_hasher")]
     pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
                                         -> HashSet<T, S> {
-        HashSet {
-            map: HashMap::with_capacity_and_hash_state(capacity, hash_state),
-        }
+        HashSet::with_capacity_and_hasher(capacity, hash_state)
     }
 
     /// Returns the number of elements the set can hold without reallocating.
@@ -604,7 +617,7 @@ impl<T, S> HashSet<T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> PartialEq for HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     fn eq(&self, other: &HashSet<T, S>) -> bool {
         if self.len() != other.len() { return false; }
@@ -615,13 +628,13 @@ impl<T, S> PartialEq for HashSet<T, S>
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Eq for HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> fmt::Debug for HashSet<T, S>
     where T: Eq + Hash + fmt::Debug,
-          S: HashState
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_set().entries(self.iter()).finish()
@@ -631,12 +644,12 @@ impl<T, S> fmt::Debug for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> FromIterator<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> HashSet<T, S> {
         let iter = iterable.into_iter();
         let lower = iter.size_hint().0;
-        let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
+        let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
         set.extend(iter);
         set
     }
@@ -645,7 +658,7 @@ impl<T, S> FromIterator<T> for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Extend<T> for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState,
+          S: BuildHasher,
 {
     fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
         for k in iter {
@@ -657,7 +670,7 @@ impl<T, S> Extend<T> for HashSet<T, S>
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
     where T: 'a + Eq + Hash + Copy,
-          S: HashState,
+          S: BuildHasher,
 {
     fn extend<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
@@ -667,17 +680,17 @@ impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> Default for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     fn default() -> HashSet<T, S> {
-        HashSet::with_hash_state(Default::default())
+        HashSet::with_hasher(Default::default())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -709,7 +722,7 @@ impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -741,7 +754,7 @@ impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -773,7 +786,7 @@ impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
     where T: Eq + Hash + Clone,
-          S: HashState + Default,
+          S: BuildHasher + Default,
 {
     type Output = HashSet<T, S>;
 
@@ -852,7 +865,7 @@ pub struct Union<'a, T: 'a, S: 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
@@ -865,7 +878,7 @@ impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T, S> IntoIterator for HashSet<T, S>
     where T: Eq + Hash,
-          S: HashState
+          S: BuildHasher
 {
     type Item = T;
     type IntoIter = IntoIter<T>;
@@ -947,7 +960,7 @@ impl<'a, T, S> Clone for Intersection<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Intersection<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -977,7 +990,7 @@ impl<'a, T, S> Clone for Difference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Difference<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -1007,7 +1020,7 @@ impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
@@ -1022,7 +1035,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Union<'a, T, S>
-    where T: Eq + Hash, S: HashState
+    where T: Eq + Hash, S: BuildHasher
 {
     type Item = &'a T;
 
diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs
index 1790eeb00b701..167aca083038e 100644
--- a/src/libstd/collections/hash/state.rs
+++ b/src/libstd/collections/hash/state.rs
@@ -10,31 +10,15 @@
 
 #![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
             issue = "27713")]
+#![rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
+#![allow(deprecated)]
 
 use clone::Clone;
 use default::Default;
 use hash;
 use marker;
 
-/// A trait representing stateful hashes which can be used to hash keys in a
-/// `HashMap`.
-///
-/// A HashState is used as a factory for instances of `Hasher` which a `HashMap`
-/// can then use to hash keys independently. A `HashMap` by default uses a state
-/// which will create instances of a `SipHasher`, but a custom state factory can
-/// be provided to the `with_hash_state` function.
-///
-/// If a hashing algorithm has no initial state, then the `Hasher` type for that
-/// algorithm can implement the `Default` trait and create hash maps with the
-/// `DefaultState` structure. This state is 0-sized and will simply delegate
-/// to `Default` when asked to create a hasher.
-pub trait HashState {
-    /// Type of the hasher that will be created.
-    type Hasher: hash::Hasher;
-
-    /// Creates a new hasher based on the given state of this object.
-    fn hasher(&self) -> Self::Hasher;
-}
+pub use hash::HashState;
 
 /// A structure which is a factory for instances of `Hasher` which implement the
 /// default trait.
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index f8550fd8842e1..316c75952667c 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -11,13 +11,12 @@
 use alloc::heap::{allocate, deallocate, EMPTY};
 
 use cmp;
-use hash::{Hash, Hasher};
+use hash::{Hash, Hasher, BuildHasher};
 use marker;
 use mem::{align_of, size_of};
 use mem;
 use ops::{Deref, DerefMut};
 use ptr::{self, Unique};
-use collections::hash_state::HashState;
 
 use self::BucketState::*;
 
@@ -144,9 +143,9 @@ impl SafeHash {
 /// This function wraps up `hash_keyed` to be the only way outside this
 /// module to generate a SafeHash.
 pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
-    where T: Hash, S: HashState
+    where T: Hash, S: BuildHasher
 {
-    let mut state = hash_state.hasher();
+    let mut state = hash_state.build_hasher();
     t.hash(&mut state);
     // We need to avoid 0 in order to prevent collisions with
     // EMPTY_HASH. We can maintain our precious uniform distribution
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 07ddfe237be93..417261cf4c304 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -444,6 +444,8 @@ pub mod hash_set {
 /// HashSet.
 #[unstable(feature = "hashmap_hasher", reason = "module was recently added",
            issue = "27713")]
+#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
+#[allow(deprecated)]
 pub mod hash_state {
     pub use super::hash::state::*;
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 9adea351e3d0e..e7bcdcc785f22 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -231,6 +231,7 @@
 #![feature(float_from_str_radix)]
 #![feature(fnbox)]
 #![feature(heap_api)]
+#![feature(hashmap_hasher)]
 #![feature(int_error_internals)]
 #![feature(into_cow)]
 #![feature(lang_items)]

From 561e165f94274c1e56a5a1ec4e5fdfbf21585b13 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Fri, 22 Jan 2016 10:17:07 -0800
Subject: [PATCH 2/2] rustc_mir: Mark the crate as unstable

Wouldn't want to be able to link to this on stable Rust!

Conflicts:
	src/librustc_mir/lib.rs
---
 src/librustc_mir/lib.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 9cc40bbc3838a..53609e65d075c 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -17,8 +17,10 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![crate_name = "rustc_mir"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
+#![unstable(feature = "rustc_private", issue = "27812")]
 
 #![feature(rustc_private)]
+#![feature(staged_api)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;