about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-09-13 18:20:27 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-09-18 11:27:10 +0200
commit67c84e05e72931587e5f81a297dee95bc149bcd8 (patch)
tree218a7eb69f31e03b0c019549c5d5392a1310bd9d /src
parentb9816c5fab6bfde01f83d83a0b53e78bb00d3900 (diff)
downloadrust-67c84e05e72931587e5f81a297dee95bc149bcd8.tar.gz
rust-67c84e05e72931587e5f81a297dee95bc149bcd8.zip
incr.comp.: Use StableHash impls instead of functions for hashing most maps.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/hcx.rs108
-rw-r--r--src/librustc/ich/impls_ty.rs83
-rw-r--r--src/librustc/ich/mod.rs4
-rw-r--r--src/librustc/lint/levels.rs31
-rw-r--r--src/librustc/middle/region.rs25
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs21
-rw-r--r--src/librustc/ty/context.rs43
-rw-r--r--src/librustc_data_structures/stable_hasher.rs50
8 files changed, 118 insertions, 247 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index bd3a3583676..0932c5ce8fb 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -14,11 +14,10 @@ use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty::{self, TyCtxt, fast_reject};
-use util::nodemap::{NodeMap, NodeSet, ItemLocalMap};
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::collections::{HashMap, HashSet, BTreeMap};
+use std::collections::HashMap;
 
 use syntax::ast;
 use syntax::attr;
@@ -337,111 +336,6 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Span {
     }
 }
 
-pub fn hash_stable_hashmap<'a, 'gcx, 'tcx, K, V, R, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &HashMap<K, V, R>,
-    extract_stable_key: F)
-    where K: Eq + std_hash::Hash,
-          V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          R: std_hash::BuildHasher,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = map.keys()
-                              .map(|k| (extract_stable_key(hcx, k), k))
-                              .collect();
-    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-    keys.len().hash_stable(hcx, hasher);
-    for (stable_key, key) in keys {
-        stable_key.hash_stable(hcx, hasher);
-        map[key].hash_stable(hcx, hasher);
-    }
-}
-
-pub fn hash_stable_hashset<'a, 'tcx, 'gcx, K, R, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    set: &HashSet<K, R>,
-    extract_stable_key: F)
-    where K: Eq + std_hash::Hash,
-          R: std_hash::BuildHasher,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = set.iter()
-                              .map(|k| extract_stable_key(hcx, k))
-                              .collect();
-    keys.sort_unstable();
-    keys.hash_stable(hcx, hasher);
-}
-
-pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &NodeMap<V>)
-    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          W: StableHasherResult,
-{
-    let definitions = hcx.tcx.hir.definitions();
-    hash_stable_hashmap(hcx, hasher, map, |_, node_id| {
-        let hir_id = definitions.node_to_hir_id(*node_id);
-        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
-        (owner_def_path_hash, hir_id.local_id)
-    });
-}
-
-pub fn hash_stable_nodeset<'a, 'tcx, 'gcx, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &NodeSet)
-    where W: StableHasherResult,
-{
-    let definitions = hcx.tcx.hir.definitions();
-    hash_stable_hashset(hcx, hasher, map, |_, node_id| {
-        let hir_id = definitions.node_to_hir_id(*node_id);
-        let owner_def_path_hash = definitions.def_path_hash(hir_id.owner);
-        (owner_def_path_hash, hir_id.local_id)
-    });
-}
-
-pub fn hash_stable_itemlocalmap<'a, 'tcx, 'gcx, V, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &ItemLocalMap<V>)
-    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          W: StableHasherResult,
-{
-    hash_stable_hashmap(hcx, hasher, map, |_, local_id| {
-        *local_id
-    });
-}
-
-
-pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>(
-    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-    hasher: &mut StableHasher<W>,
-    map: &BTreeMap<K, V>,
-    extract_stable_key: F)
-    where K: Eq + Ord,
-          V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
-          SK: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + Ord + Clone,
-          F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK,
-          W: StableHasherResult,
-{
-    let mut keys: Vec<_> = map.keys()
-                              .map(|k| (extract_stable_key(hcx, k), k))
-                              .collect();
-    keys.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-    keys.len().hash_stable(hcx, hasher);
-    for (stable_key, key) in keys {
-        stable_key.hash_stable(hcx, hasher);
-        map[key].hash_stable(hcx, hasher);
-    }
-}
-
 pub fn hash_stable_trait_impls<'a, 'tcx, 'gcx, W, R>(
     hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
     hasher: &mut StableHasher<W>,
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 53a071fe480..371a9c96644 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -11,9 +11,9 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::{self, StableHashingContext, NodeIdHashingMode};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use ich::{StableHashingContext, NodeIdHashingMode};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
 use middle::region;
@@ -124,9 +124,10 @@ for ty::adjustment::Adjust<'gcx> {
 
 impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
 impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl });
-impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
 impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
 
+impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
+
 impl_stable_hash_for!(enum ty::BorrowKind {
     ImmBorrow,
     UniqueImmBorrow,
@@ -513,28 +514,20 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
     FnPtrAddrCast
 });
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for region::Scope
-{
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            match *self {
-                region::Scope::Node(node_id) |
-                region::Scope::Destruction(node_id) => {
-                    node_id.hash_stable(hcx, hasher);
-                }
-                region::Scope::CallSite(body_id) |
-                region::Scope::Arguments(body_id) => {
-                    body_id.hash_stable(hcx, hasher);
-                }
-                region::Scope::Remainder(block_remainder) => {
-                    block_remainder.hash_stable(hcx, hasher);
-                }
-            }
-        })
+impl_stable_hash_for!(enum ::middle::region::Scope {
+    Node(local_id),
+    Destruction(local_id),
+    CallSite(local_id),
+    Arguments(local_id),
+    Remainder(block_remainder)
+});
+
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for region::Scope {
+    type KeyType = region::Scope;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'a, 'gcx, 'tcx>) -> region::Scope {
+        *self
     }
 }
 
@@ -770,10 +763,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Cr
         } = *self;
 
         dependencies.hash_stable(hcx, hasher);
-
-        ich::hash_stable_hashmap(hcx, hasher, variances, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
+        variances.hash_stable(hcx, hasher);
     }
 }
 
@@ -836,25 +826,14 @@ for ::middle::privacy::AccessLevels {
                 ref map
             } = *self;
 
-            ich::hash_stable_nodemap(hcx, hasher, map);
+            map.hash_stable(hcx, hasher);
         });
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ty::CrateInherentImpls {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let ty::CrateInherentImpls {
-            ref inherent_impls,
-        } = *self;
-
-        ich::hash_stable_hashmap(hcx, hasher, inherent_impls, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-    }
-}
+impl_stable_hash_for!(struct ty::CrateInherentImpls {
+    inherent_impls
+});
 
 impl_stable_hash_for!(enum ::session::CompileIncomplete {
     Stopped,
@@ -863,14 +842,6 @@ impl_stable_hash_for!(enum ::session::CompileIncomplete {
 
 impl_stable_hash_for!(struct ::util::common::ErrorReported {});
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
-for ::middle::reachable::ReachableSet {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let ::middle::reachable::ReachableSet(ref reachable_set) = *self;
-
-        ich::hash_stable_nodeset(hcx, hasher, reachable_set);
-    }
-}
-
+impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet {
+    reachable_set
+});
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index 5558534b71d..cd0749a6865 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -12,9 +12,7 @@
 
 pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
-pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
-                    hash_stable_hashset, hash_stable_nodemap, hash_stable_nodeset,
-                    hash_stable_btreemap, hash_stable_itemlocalmap,
+pub use self::hcx::{StableHashingContext, NodeIdHashingMode,
                     hash_stable_trait_impls};
 mod fingerprint;
 mod caching_codemap_view;
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index e953afd799d..eb2b136e417 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -12,12 +12,12 @@ use std::cmp;
 
 use errors::DiagnosticBuilder;
 use hir::HirId;
-use ich::{self, StableHashingContext};
+use ich::StableHashingContext;
 use lint::builtin;
 use lint::context::CheckLintNameResult;
 use lint::{self, Lint, LintId, Level, LintSource};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
+                                           StableHasher, StableHasherResult};
 use session::Session;
 use syntax::ast;
 use syntax::attr;
@@ -396,10 +396,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
             ref id_to_set,
         } = *self;
 
-        let definitions = hcx.tcx().hir.definitions();
-        ich::hash_stable_hashmap(hcx, hasher, id_to_set, |_, hir_id| {
-            (definitions.def_path_hash(hir_id.owner), hir_id.local_id)
-        });
+        id_to_set.hash_stable(hcx, hasher);
 
         let LintLevelSets {
             ref list,
@@ -418,14 +415,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
 
                 match *lint_set {
                     LintSet::CommandLine { ref specs } => {
-                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
-                            lint_id.lint_name_raw()
-                        });
+                        specs.hash_stable(hcx, hasher);
                     }
                     LintSet::Node { ref specs, parent } => {
-                        ich::hash_stable_hashmap(hcx, hasher, specs, |_, lint_id| {
-                            lint_id.lint_name_raw()
-                        });
+                        specs.hash_stable(hcx, hasher);
                         parent.hash_stable(hcx, hasher);
                     }
                 }
@@ -434,12 +427,20 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintLe
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for LintId {
+impl<HCX> HashStable<HCX> for LintId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
         self.lint_name_raw().hash_stable(hcx, hasher);
     }
 }
 
+impl<HCX> ToStableHashKey<HCX> for LintId {
+    type KeyType = &'static str;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
+        self.lint_name_raw()
+    }
+}
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 562536ced3c..5c6feddb1fd 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -14,7 +14,7 @@
 //! Most of the documentation on regions can be found in
 //! `middle/infer/region_inference/README.md`
 
-use ich::{self, StableHashingContext, NodeIdHashingMode};
+use ich::{StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty;
 
@@ -1259,22 +1259,11 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ScopeT
             root_parent.hash_stable(hcx, hasher);
         });
 
-        ich::hash_stable_hashmap(hcx, hasher, parent_map, |hcx, scope| {
-            let mut hasher = StableHasher::new();
-            scope.hash_stable(hcx, &mut hasher);
-            let stable: u64 = hasher.finish();
-            stable
-        });
-
-        ich::hash_stable_itemlocalmap(hcx, hasher, var_map);
-        ich::hash_stable_itemlocalmap(hcx, hasher, destruction_scopes);
-        ich::hash_stable_itemlocalmap(hcx, hasher, rvalue_scopes);
-        ich::hash_stable_itemlocalmap(hcx, hasher, closure_tree);
-        ich::hash_stable_hashmap(hcx, hasher, yield_in_scope, |hcx, scope| {
-            let mut hasher = StableHasher::new();
-            scope.hash_stable(hcx, &mut hasher);
-            let stable: u64 = hasher.finish();
-            stable
-        });
+        parent_map.hash_stable(hcx, hasher);
+        var_map.hash_stable(hcx, hasher);
+        destruction_scopes.hash_stable(hcx, hasher);
+        rvalue_scopes.hash_stable(hcx, hasher);
+        closure_tree.hash_stable(hcx, hasher);
+        yield_in_scope.hash_stable(hcx, hasher);
     }
 }
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index ecaf14659ae..6895e0e8a34 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -382,20 +382,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Childr
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Graph {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let Graph {
-            ref parent,
-            ref children,
-        } = *self;
-
-        ich::hash_stable_hashmap(hcx, hasher, parent, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-        ich::hash_stable_hashmap(hcx, hasher, children, |hcx, def_id| {
-            hcx.def_path_hash(*def_id)
-        });
-    }
-}
+impl_stable_hash_for!(struct self::Graph {
+    parent,
+    children
+});
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7edc55e8a9f..0ea466a1bbc 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -21,7 +21,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::DefPathHash;
 use lint::{self, Lint};
-use ich::{self, StableHashingContext, NodeIdHashingMode};
+use ich::{StableHashingContext, NodeIdHashingMode};
 use middle::const_val::ConstVal;
 use middle::cstore::{CrateStore, LinkMeta, EncodedMetadataHashes};
 use middle::cstore::EncodedMetadata;
@@ -49,8 +49,8 @@ use ty::BindingMode;
 use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
-                                           StableHasherResult};
+use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
+                                           StableHasher, StableHasherResult};
 
 use arena::{TypedArena, DroplessArena};
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -714,12 +714,12 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Typeck
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            ich::hash_stable_itemlocalmap(hcx, hasher, type_dependent_defs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, node_types);
-            ich::hash_stable_itemlocalmap(hcx, hasher, node_substs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, adjustments);
-            ich::hash_stable_itemlocalmap(hcx, hasher, pat_binding_modes);
-            ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
+            type_dependent_defs.hash_stable(hcx, hasher);
+            node_types.hash_stable(hcx, hasher);
+            node_substs.hash_stable(hcx, hasher);
+            adjustments.hash_stable(hcx, hasher);
+            pat_binding_modes.hash_stable(hcx, hasher);
+            hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
                 let ty::UpvarId {
                     var_id,
                     closure_expr_id
@@ -736,22 +736,19 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Typeck
                     krate: local_id_root.krate,
                     index: closure_expr_id,
                 };
-                ((hcx.def_path_hash(var_owner_def_id), var_id.local_id),
-                 hcx.def_path_hash(closure_def_id))
-            });
-
-            ich::hash_stable_itemlocalmap(hcx, hasher, closure_tys);
-            ich::hash_stable_itemlocalmap(hcx, hasher, closure_kinds);
-            ich::hash_stable_itemlocalmap(hcx, hasher, liberated_fn_sigs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, fru_field_types);
-            ich::hash_stable_itemlocalmap(hcx, hasher, cast_kinds);
-            ich::hash_stable_itemlocalmap(hcx, hasher, generator_sigs);
-            ich::hash_stable_itemlocalmap(hcx, hasher, generator_interiors);
-
-            ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
-                hcx.def_path_hash(*def_id)
+                (hcx.tcx().def_path_hash(var_owner_def_id),
+                 var_id.local_id,
+                 hcx.tcx().def_path_hash(closure_def_id))
             });
 
+            closure_tys.hash_stable(hcx, hasher);
+            closure_kinds.hash_stable(hcx, hasher);
+            liberated_fn_sigs.hash_stable(hcx, hasher);
+            fru_field_types.hash_stable(hcx, hasher);
+            cast_kinds.hash_stable(hcx, hasher);
+            generator_sigs.hash_stable(hcx, hasher);
+            generator_interiors.hash_stable(hcx, hasher);
+            used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
             free_region_map.hash_stable(hcx, hasher);
         })
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index 1b2d09bef93..e18c1969a91 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -289,7 +289,8 @@ impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(ctx, hasher);
+        let (ref _0,) = *self;
+        _0.hash_stable(ctx, hasher);
     }
 }
 
@@ -297,8 +298,24 @@ impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2)
     fn hash_stable<W: StableHasherResult>(&self,
                                           ctx: &mut CTX,
                                           hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(ctx, hasher);
-        self.1.hash_stable(ctx, hasher);
+        let (ref _0, ref _1) = *self;
+        _0.hash_stable(ctx, hasher);
+        _1.hash_stable(ctx, hasher);
+    }
+}
+
+impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
+     where T1: HashStable<CTX>,
+           T2: HashStable<CTX>,
+           T3: HashStable<CTX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        let (ref _0, ref _1, ref _2) = *self;
+        _0.hash_stable(ctx, hasher);
+        _1.hash_stable(ctx, hasher);
+        _2.hash_stable(ctx, hasher);
     }
 }
 
@@ -462,14 +479,11 @@ impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
           V: HashStable<HCX>,
           R: BuildHasher,
 {
+    #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut HCX,
                                           hasher: &mut StableHasher<W>) {
-        let mut entries: Vec<_> = self.iter()
-                                      .map(|(k, v)| (k.to_stable_hash_key(hcx), v))
-                                      .collect();
-        entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
-        entries.hash_stable(hcx, hasher);
+        hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key);
     }
 }
 
@@ -516,3 +530,23 @@ impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
         keys.hash_stable(hcx, hasher);
     }
 }
+
+pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>(
+    hcx: &mut HCX,
+    hasher: &mut StableHasher<W>,
+    map: &::std::collections::HashMap<K, V, R>,
+    to_stable_hash_key: F)
+    where K: Eq + Hash,
+          V: HashStable<HCX>,
+          R: BuildHasher,
+          SK: HashStable<HCX> + Ord + Clone,
+          F: Fn(&K, &HCX) -> SK,
+          W: StableHasherResult,
+{
+    let mut entries: Vec<_> = map.iter()
+                                  .map(|(k, v)| (to_stable_hash_key(k, hcx), v))
+                                  .collect();
+    entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
+    entries.hash_stable(hcx, hasher);
+}
+