about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-01-16 10:16:38 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:34:08 +0100
commit7d2d4e320294d69f6fff3002200b7ea8809b95d1 (patch)
tree9fb7eb37c4977c528d2b38d0bb5cc6dc27f4c81b /src
parente0045ab8915c85e35dd04e9f9d00d6d011237bfa (diff)
downloadrust-7d2d4e320294d69f6fff3002200b7ea8809b95d1.tar.gz
rust-7d2d4e320294d69f6fff3002200b7ea8809b95d1.zip
Add InterpretInterner to StableHashingContext for AllocId serialization
Diffstat (limited to 'src')
-rw-r--r--src/librustc/dep_graph/dep_node.rs2
-rw-r--r--src/librustc/hir/map/collector.rs2
-rw-r--r--src/librustc/ich/hcx.rs64
-rw-r--r--src/librustc/ich/impls_hir.rs132
-rw-r--r--src/librustc/ich/impls_mir.rs98
-rw-r--r--src/librustc/ich/impls_syntax.rs48
-rw-r--r--src/librustc/ich/impls_ty.rs206
-rw-r--r--src/librustc/lint/levels.rs4
-rw-r--r--src/librustc/macros.rs16
-rw-r--r--src/librustc/middle/borrowck.rs4
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/mir/cache.rs4
-rw-r--r--src/librustc/mir/interpret/mod.rs2
-rw-r--r--src/librustc/mir/mod.rs2
-rw-r--r--src/librustc/mir/mono.rs8
-rw-r--r--src/librustc/session/config.rs4
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs4
-rw-r--r--src/librustc/ty/context.rs6
-rw-r--r--src/librustc/ty/fast_reject.rs6
-rw-r--r--src/librustc/ty/layout.rs20
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc/ty/trait_def.rs4
-rw-r--r--src/librustc_metadata/schema.rs8
-rw-r--r--src/librustc_mir/build/matches/test.rs144
-rw-r--r--src/librustc_mir/diagnostics.rs30
-rw-r--r--src/librustc_mir/interpret/const_eval.rs9
-rw-r--r--src/librustc_mir/interpret/eval_context.rs14
-rw-r--r--src/librustc_mir/interpret/memory.rs6
-rw-r--r--src/librustc_mir/interpret/traits.rs2
-rw-r--r--src/librustc_mir/transform/instcombine.rs54
-rw-r--r--src/librustc_mir/transform/mod.rs1
-rw-r--r--src/librustc_trans/mir/analyze.rs2
-rw-r--r--src/librustc_trans/mir/block.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs100
-rw-r--r--src/librustc_trans/mir/operand.rs24
-rw-r--r--src/librustdoc/clean/mod.rs53
-rw-r--r--src/test/compile-fail/const-err2.rs4
-rw-r--r--src/test/compile-fail/const-err3.rs3
-rw-r--r--src/test/run-pass/ctfe/references.rs34
39 files changed, 618 insertions, 528 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 6824c015eab..7d8709a82f4 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -661,7 +661,7 @@ trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
 }
 
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
-    where T: HashStable<StableHashingContext<'gcx>> + fmt::Debug
+    where T: HashStable<StableHashingContext<'a>> + fmt::Debug
 {
     default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
 
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 9bbda9d7447..3c523f5633e 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -529,7 +529,7 @@ struct HirItemLike<T> {
     hash_bodies: bool,
 }
 
-impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
+impl<'a, 'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
     where T: HashStable<StableHashingContext<'hir>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 4dcab6a04ee..6ae588b2a07 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -46,19 +46,19 @@ pub fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
 /// a reference to the TyCtxt) and it holds a few caches for speeding up various
 /// things (e.g. each DefId/DefPath is only hashed once).
 #[derive(Clone)]
-pub struct StableHashingContext<'gcx> {
-    sess: &'gcx Session,
-    definitions: &'gcx Definitions,
-    cstore: &'gcx dyn CrateStore,
-    body_resolver: BodyResolver<'gcx>,
+pub struct StableHashingContext<'a> {
+    sess: &'a Session,
+    definitions: &'a Definitions,
+    cstore: &'a dyn CrateStore,
+    body_resolver: BodyResolver<'a>,
     hash_spans: bool,
     hash_bodies: bool,
     node_id_hashing_mode: NodeIdHashingMode,
 
     // Very often, we are hashing something that does not need the
     // CachingCodemapView, so we initialize it lazily.
-    raw_codemap: &'gcx CodeMap,
-    caching_codemap: Option<CachingCodemapView<'gcx>>,
+    raw_codemap: &'a CodeMap,
+    caching_codemap: Option<CachingCodemapView<'a>>,
 }
 
 #[derive(PartialEq, Eq, Clone, Copy)]
@@ -81,14 +81,14 @@ impl<'gcx> BodyResolver<'gcx> {
     }
 }
 
-impl<'gcx> StableHashingContext<'gcx> {
+impl<'a> StableHashingContext<'a> {
     // The `krate` here is only used for mapping BodyIds to Bodies.
     // Don't use it for anything else or you'll run the risk of
     // leaking data out of the tracking system.
-    pub fn new(sess: &'gcx Session,
-               krate: &'gcx hir::Crate,
-               definitions: &'gcx Definitions,
-               cstore: &'gcx dyn CrateStore)
+    pub fn new(sess: &'a Session,
+               krate: &'a hir::Crate,
+               definitions: &'a Definitions,
+               cstore: &'a dyn CrateStore)
                -> Self {
         let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
 
@@ -106,7 +106,7 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 
     #[inline]
-    pub fn sess(&self) -> &'gcx Session {
+    pub fn sess(&self) -> &'a Session {
         self.sess
     }
 
@@ -165,7 +165,7 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 
     #[inline]
-    pub fn codemap(&mut self) -> &mut CachingCodemapView<'gcx> {
+    pub fn codemap(&mut self) -> &mut CachingCodemapView<'a> {
         match self.caching_codemap {
             Some(ref mut cm) => {
                 cm
@@ -193,27 +193,27 @@ impl<'gcx> StableHashingContext<'gcx> {
 }
 
 impl<'a, 'gcx, 'lcx> StableHashingContextProvider for TyCtxt<'a, 'gcx, 'lcx> {
-    type ContextType = StableHashingContext<'gcx>;
+    type ContextType = StableHashingContext<'a>;
     fn create_stable_hashing_context(&self) -> Self::ContextType {
         (*self).create_stable_hashing_context()
     }
 }
 
 
-impl<'gcx> StableHashingContextProvider for StableHashingContext<'gcx> {
-    type ContextType = StableHashingContext<'gcx>;
+impl<'a> StableHashingContextProvider for StableHashingContext<'a> {
+    type ContextType = StableHashingContext<'a>;
     fn create_stable_hashing_context(&self) -> Self::ContextType {
         self.clone()
     }
 }
 
-impl<'gcx> ::dep_graph::DepGraphSafe for StableHashingContext<'gcx> {
+impl<'a> ::dep_graph::DepGraphSafe for StableHashingContext<'a> {
 }
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::BodyId {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         if hcx.hash_bodies() {
             hcx.body_resolver.body(*self).hash_stable(hcx, hasher);
@@ -221,10 +221,10 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::BodyId {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::HirId {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::HirId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
@@ -243,21 +243,21 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::HirId {
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::HirId {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::HirId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'gcx>)
+                          hcx: &StableHashingContext<'a>)
                           -> (DefPathHash, hir::ItemLocalId) {
         let def_path_hash = hcx.local_def_path_hash(self.owner);
         (def_path_hash, self.local_id)
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::NodeId {
+impl<'a> HashStable<StableHashingContext<'a>> for ast::NodeId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         match hcx.node_id_hashing_mode {
             NodeIdHashingMode::Ignore => {
@@ -270,18 +270,18 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::NodeId {
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for ast::NodeId {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::NodeId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'gcx>)
+                          hcx: &StableHashingContext<'a>)
                           -> (DefPathHash, hir::ItemLocalId) {
         hcx.definitions.node_to_hir_id(*self).to_stable_hash_key(hcx)
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
+impl<'a> HashStable<StableHashingContext<'a>> for Span {
 
     // Hash a span in a stable way. We can't directly hash the span's BytePos
     // fields (that would be similar to hashing pointers, since those are just
@@ -293,7 +293,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
     // Also, hashing filenames is expensive so we avoid doing it twice when the
     // span starts and ends in the same file, which is almost always the case.
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         const TAG_VALID_SPAN: u8 = 0;
         const TAG_INVALID_SPAN: u8 = 1;
@@ -373,8 +373,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
     }
 }
 
-pub fn hash_stable_trait_impls<'gcx, W, R>(
-    hcx: &mut StableHashingContext<'gcx>,
+pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
+    hcx: &mut StableHashingContext<'a>,
     hasher: &mut StableHasher<W>,
     blanket_impls: &Vec<DefId>,
     non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index faad3f35631..c085b803085 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -21,46 +21,46 @@ use std::mem;
 use syntax::ast;
 use syntax::attr;
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId {
+impl<'a> HashStable<StableHashingContext<'a>> for DefId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.def_path_hash(*self).hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for DefId {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for DefId {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
         hcx.def_path_hash(*self)
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for LocalDefId {
+impl<'a> HashStable<StableHashingContext<'a>> for LocalDefId {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for LocalDefId {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalDefId {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
         hcx.def_path_hash(self.to_def_id())
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for CrateNum {
+impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.def_path_hash(DefId {
             krate: *self,
@@ -69,11 +69,11 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for CrateNum {
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for CrateNum {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
         def_id.to_stable_hash_key(hcx)
     }
@@ -81,13 +81,13 @@ impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for CrateNum {
 
 impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index });
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>>
+impl<'a> ToStableHashKey<StableHashingContext<'a>>
 for hir::ItemLocalId {
     type KeyType = hir::ItemLocalId;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'gcx>)
+                          _: &StableHashingContext<'a>)
                           -> hir::ItemLocalId {
         *self
     }
@@ -100,9 +100,9 @@ for hir::ItemLocalId {
 // want to pick up on a reference changing its target, so we hash the NodeIds
 // in "DefPath Mode".
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ItemId {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::ItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ItemId {
             id
@@ -114,9 +114,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ItemId {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItemId {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItemId {
             node_id
@@ -128,9 +128,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItemId {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItemId {
             node_id
@@ -271,9 +271,9 @@ impl_stable_hash_for!(struct hir::TypeBinding {
     span
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Ty {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Ty {
@@ -339,9 +339,9 @@ impl_stable_hash_for!(enum hir::FunctionRetTy {
     Return(t)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitRef {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitRef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitRef {
             ref path,
@@ -376,9 +376,9 @@ impl_stable_hash_for!(struct hir::MacroDef {
 });
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Block {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Block {
             ref stmts,
@@ -400,9 +400,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Pat {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Pat {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Pat {
             id: _,
@@ -527,9 +527,9 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
     UserProvided
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Expr {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Expr {
@@ -591,9 +591,9 @@ impl_stable_hash_for!(enum hir::LoopSource {
     ForLoop
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::MatchSource {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::MatchSource {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use hir::MatchSource;
 
@@ -647,9 +647,9 @@ impl_stable_hash_for!(enum hir::ScopeTarget {
     Loop(loop_id_result)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Ident {
+impl<'a> HashStable<StableHashingContext<'a>> for ast::Ident {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ast::Ident {
             ref name,
@@ -660,9 +660,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Ident {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
             id: _,
@@ -695,9 +695,9 @@ impl_stable_hash_for!(enum hir::TraitItemKind {
     Type(bounds, rhs)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
             id: _,
@@ -729,9 +729,9 @@ impl_stable_hash_for!(enum hir::ImplItemKind {
     Type(t)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Visibility {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -750,9 +750,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Visibility {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Defaultness {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Defaultness {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -771,9 +771,9 @@ impl_stable_hash_for!(enum hir::ImplPolarity {
     Negative
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Mod {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Mod {
             inner,
@@ -826,9 +826,9 @@ impl_stable_hash_for!(enum hir::VariantData {
     Unit(id)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Item {
             name,
@@ -885,10 +885,10 @@ impl_stable_hash_for!(struct hir::ImplItemRef {
     defaultness
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for hir::AssociatedItemKind {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -930,9 +930,9 @@ impl_stable_hash_for!(struct hir::Arg {
     hir_id
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Body {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Body {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::Body {
             ref arguments,
@@ -948,12 +948,12 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Body {
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::BodyId {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
     type KeyType = (DefPathHash, hir::ItemLocalId);
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'gcx>)
+                          hcx: &StableHashingContext<'a>)
                           -> (DefPathHash, hir::ItemLocalId) {
         let hir::BodyId { node_id } = *self;
         node_id.to_stable_hash_key(hcx)
@@ -966,9 +966,9 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput {
     is_indirect
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::GlobalAsm {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::GlobalAsm {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::GlobalAsm {
             asm,
@@ -979,9 +979,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::GlobalAsm {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::InlineAsm {
+impl<'a> HashStable<StableHashingContext<'a>> for hir::InlineAsm {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let hir::InlineAsm {
             asm,
@@ -1062,22 +1062,22 @@ impl_stable_hash_for!(enum hir::Constness {
     NotConst
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for hir::def_id::DefIndex {
 
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.local_def_path_hash(*self).hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>>
+impl<'a> ToStableHashKey<StableHashingContext<'a>>
 for hir::def_id::DefIndex {
     type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
          hcx.local_def_path_hash(*self)
     }
 }
@@ -1090,10 +1090,10 @@ impl_stable_hash_for!(struct hir::def::Export {
     is_import
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for ::middle::lang_items::LangItem {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'gcx>,
+                                          _: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         ::std::hash::Hash::hash(self, hasher);
     }
@@ -1104,10 +1104,10 @@ impl_stable_hash_for!(struct ::middle::lang_items::LanguageItems {
     missing
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for hir::TraitCandidate {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             let hir::TraitCandidate {
@@ -1121,11 +1121,11 @@ for hir::TraitCandidate {
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
     type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);
 
     fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'gcx>)
+                          hcx: &StableHashingContext<'a>)
                           -> Self::KeyType {
         let hir::TraitCandidate {
             def_id,
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 40204943bb5..1e6dadae363 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -35,11 +35,11 @@ impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator,
 impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind });
 impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for mir::BorrowKind {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -54,11 +54,11 @@ for mir::BorrowKind {
 }
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for mir::UnsafetyViolationKind {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
 
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -79,12 +79,12 @@ impl_stable_hash_for!(struct mir::Terminator<'tcx> {
     source_info
 });
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearCrossCrate<T>
-    where T: HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for mir::ClearCrossCrate<T>
+    where T: HashStable<StableHashingContext<'a>>
 {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -96,61 +96,61 @@ impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearCrossCrate<T>
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local {
+impl<'a> HashStable<StableHashingContext<'a>> for mir::Local {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::BasicBlock {
+impl<'a> HashStable<StableHashingContext<'a>> for mir::BasicBlock {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Field {
+impl<'a> HashStable<StableHashingContext<'a>> for mir::Field {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for mir::VisibilityScope {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Promoted {
+impl<'a> HashStable<StableHashingContext<'a>> for mir::Promoted {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for mir::TerminatorKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -227,10 +227,10 @@ for mir::TerminatorKind<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for mir::AssertMessage<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -250,10 +250,10 @@ for mir::AssertMessage<'gcx> {
 
 impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for mir::StatementKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -287,12 +287,12 @@ for mir::StatementKind<'gcx> {
     }
 }
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
     for mir::ValidationOperand<'gcx, T>
-    where T: HashStable<StableHashingContext<'gcx>>
+    where T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>)
     {
         self.place.hash_stable(hcx, hasher);
@@ -304,9 +304,9 @@ impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
 
 impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(region_scope) });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Place<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -323,14 +323,14 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Place<'gcx> {
     }
 }
 
-impl<'gcx, B, V, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, B, V, T> HashStable<StableHashingContext<'a>>
 for mir::Projection<'gcx, B, V, T>
-    where B: HashStable<StableHashingContext<'gcx>>,
-          V: HashStable<StableHashingContext<'gcx>>,
-          T: HashStable<StableHashingContext<'gcx>>
+    where B: HashStable<StableHashingContext<'a>>,
+          V: HashStable<StableHashingContext<'a>>,
+          T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let mir::Projection {
             ref base,
@@ -342,13 +342,13 @@ for mir::Projection<'gcx, B, V, T>
     }
 }
 
-impl<'gcx, V, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, V, T> HashStable<StableHashingContext<'a>>
 for mir::ProjectionElem<'gcx, V, T>
-    where V: HashStable<StableHashingContext<'gcx>>,
-          T: HashStable<StableHashingContext<'gcx>>
+    where V: HashStable<StableHashingContext<'a>>,
+          T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -382,9 +382,9 @@ impl_stable_hash_for!(struct mir::VisibilityScopeInfo {
     lint_root, safety
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Safety {
+impl<'a> HashStable<StableHashingContext<'a>> for mir::Safety {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -399,9 +399,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Safety {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Operand<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -419,9 +419,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Rvalue<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Rvalue<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -479,10 +479,10 @@ impl_stable_hash_for!(enum mir::CastKind {
     Unsize
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for mir::AggregateKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -541,9 +541,9 @@ impl_stable_hash_for!(enum mir::NullOp {
 
 impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Literal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -570,9 +570,9 @@ impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
     blame_span
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::ClosureOutlivesSubject<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubject<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index f935cbfcde9..52f43fbed7b 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -29,42 +29,42 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for InternedString {
+impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let s: &str = &**self;
         s.hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for InternedString {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
     type KeyType = InternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'gcx>)
+                          _: &StableHashingContext<'a>)
                           -> InternedString {
         self.clone()
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Name {
+impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         self.as_str().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for ast::Name {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
     type KeyType = InternedString;
 
     #[inline]
     fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'gcx>)
+                          _: &StableHashingContext<'a>)
                           -> InternedString {
         self.as_str()
     }
@@ -111,10 +111,10 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
     rustc_const_unstable
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for ::syntax::attr::StabilityLevel {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -166,9 +166,9 @@ impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for [ast::Attribute] {
+impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         if self.len() == 0 {
             self.len().hash_stable(hcx, hasher);
@@ -191,9 +191,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for [ast::Attribute] {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
+impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         // Make sure that these have been filtered out.
         debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
@@ -220,10 +220,10 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for tokenstream::TokenTree {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -242,10 +242,10 @@ for tokenstream::TokenTree {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for tokenstream::TokenStream {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         for sub_tt in self.trees() {
             sub_tt.hash_stable(hcx, hasher);
@@ -253,9 +253,11 @@ for tokenstream::TokenStream {
     }
 }
 
-fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
-                                           hcx: &mut StableHashingContext<'gcx>,
-                                           hasher: &mut StableHasher<W>) {
+fn hash_token<'a, 'gcx, W: StableHasherResult>(
+    token: &token::Token,
+    hcx: &mut StableHashingContext<'a>,
+    hasher: &mut StableHasher<W>,
+) {
     mem::discriminant(token).hash_stable(hcx, hasher);
     match *token {
         token::Token::Eq |
@@ -383,9 +385,9 @@ impl_stable_hash_for!(enum ::syntax_pos::FileName {
     Custom(s)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
+impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let FileMap {
             name: _, // We hash the smaller name_hash instead of this
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index a25741c95aa..a92d9b16612 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -23,11 +23,11 @@ use traits;
 use ty;
 use mir;
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
 for &'gcx ty::Slice<T>
-    where T: HashStable<StableHashingContext<'gcx>> {
+    where T: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         thread_local! {
             static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
@@ -52,10 +52,10 @@ for &'gcx ty::Slice<T>
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::subst::Kind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         self.unpack().hash_stable(hcx, hasher);
     }
@@ -73,10 +73,10 @@ for ty::subst::UnpackedKind<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for ty::RegionKind {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -120,20 +120,20 @@ for ty::RegionKind {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::RegionVid {
+impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use rustc_data_structures::indexed_vec::Idx;
         self.index().hash_stable(hcx, hasher);
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::adjustment::AutoBorrow<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -148,10 +148,10 @@ for ty::adjustment::AutoBorrow<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::adjustment::Adjust<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -197,10 +197,10 @@ impl_stable_hash_for!(enum ty::BorrowKind {
     MutBorrow
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::UpvarCapture<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -224,11 +224,11 @@ impl_stable_hash_for!(struct ty::FnSig<'tcx> {
     abi
 });
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for ty::Binder<T>
-    where T: HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
+    where T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::Binder(ref inner) = *self;
         inner.hash_stable(hcx, hasher);
@@ -247,13 +247,13 @@ impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
 impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
 impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
 
-impl<'gcx, A, B> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, A, B> HashStable<StableHashingContext<'a>>
 for ty::OutlivesPredicate<A, B>
-    where A: HashStable<StableHashingContext<'gcx>>,
-          B: HashStable<StableHashingContext<'gcx>>,
+    where A: HashStable<StableHashingContext<'a>>,
+          B: HashStable<StableHashingContext<'a>>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::OutlivesPredicate(ref a, ref b) = *self;
         a.hash_stable(hcx, hasher);
@@ -265,9 +265,9 @@ impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty }
 impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id });
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Predicate<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::Predicate<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -305,9 +305,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Predicate<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::AdtFlags {
+impl<'a> HashStable<StableHashingContext<'a>> for ty::AdtFlags {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'gcx>,
+                                          _: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         std_hash::Hash::hash(self, hasher);
     }
@@ -332,10 +332,10 @@ impl_stable_hash_for!(struct ty::FieldDef {
     vis
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ::middle::const_val::ConstVal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use middle::const_val::ConstVal::*;
 
@@ -368,7 +368,51 @@ impl_stable_hash_for!(struct mir::interpret::MemoryPointer {
     offset
 });
 
-impl_stable_hash_for!(tuple_struct mir::interpret::AllocId{id});
+impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        ty::tls::with_opt(|tcx| {
+            let tcx = tcx.expect("can't hash AllocIds during hir lowering");
+            let interner = tcx
+                .interpret_interner
+                .borrow();
+            if let Some(def_id) = interner.get_corresponding_static_def_id(*self) {
+                0.hash_stable(hcx, hasher);
+                // statics are unique via their DefId
+                def_id.hash_stable(hcx, hasher);
+            } else if let Some(alloc) = interner.get_alloc(*self) {
+                // not a static, can't be recursive, hash the allocation
+                1.hash_stable(hcx, hasher);
+                alloc.hash_stable(hcx, hasher);
+            } else if let Some(inst) = interner.get_fn(*self) {
+                2.hash_stable(hcx, hasher);
+                inst.hash_stable(hcx, hasher);
+            } else {
+                bug!("no allocation for {}", self);
+            }
+        });
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::Allocation {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        self.bytes.hash_stable(hcx, hasher);
+        for reloc in self.relocations.iter() {
+            reloc.hash_stable(hcx, hasher);
+        }
+        self.undef_mask.hash_stable(hcx, hasher);
+        self.align.hash_stable(hcx, hasher);
+        self.mutable.hash_stable(hcx, hasher);
+    }
+}
+
 impl_stable_hash_for!(struct mir::interpret::Pointer{primval});
 
 impl_stable_hash_for!(enum mir::interpret::PrimVal {
@@ -387,10 +431,10 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
     kind
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ::middle::const_val::ErrKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use middle::const_val::ErrKind::*;
 
@@ -441,10 +485,10 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     predicates
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ::mir::interpret::EvalError<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use mir::interpret::EvalErrorKind::*;
 
@@ -621,9 +665,9 @@ impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized {
     Struct(index)
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Generics {
+impl<'a> HashStable<StableHashingContext<'a>> for ty::Generics {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::Generics {
             parent,
@@ -649,10 +693,10 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Generics {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for ty::RegionParameterDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::RegionParameterDef {
             name,
@@ -678,12 +722,12 @@ impl_stable_hash_for!(struct ty::TypeParameterDef {
     synthetic
 });
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
 for ::middle::resolve_lifetime::Set1<T>
-    where T: HashStable<StableHashingContext<'gcx>>
+    where T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use middle::resolve_lifetime::Set1;
 
@@ -734,11 +778,11 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
 impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx });
 impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
 
-impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
     type KeyType = region::Scope;
 
     #[inline]
-    fn to_stable_hash_key(&self, _: &StableHashingContext<'gcx>) -> region::Scope {
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> region::Scope {
         *self
     }
 }
@@ -764,11 +808,11 @@ impl_stable_hash_for!(enum ty::BoundRegion {
     BrEnv
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::TypeVariants<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use ty::TypeVariants::*;
 
@@ -865,11 +909,11 @@ impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
     mutbl
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ty::ExistentialPredicate<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
@@ -902,9 +946,9 @@ impl_stable_hash_for!(struct ty::Instance<'tcx> {
     substs
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::InstanceDef<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -938,9 +982,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TraitDef {
+impl<'a> HashStable<StableHashingContext<'a>> for ty::TraitDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TraitDef {
             // We already have the def_path_hash below, no need to hash it twice
@@ -968,9 +1012,9 @@ impl_stable_hash_for!(struct ty::DtorckConstraint<'tcx> {
 });
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CrateVariancesMap {
+impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::CrateVariancesMap {
             ref variances,
@@ -1004,12 +1048,12 @@ impl_stable_hash_for!(enum ty::AssociatedItemContainer {
 });
 
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
 for ty::steal::Steal<T>
-    where T: HashStable<StableHashingContext<'gcx>>
+    where T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         self.borrow().hash_stable(hcx, hasher);
     }
@@ -1032,10 +1076,10 @@ impl_stable_hash_for!(enum ::middle::privacy::AccessLevel {
     Public
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
+impl<'a> HashStable<StableHashingContext<'a>>
 for ::middle::privacy::AccessLevels {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             let ::middle::privacy::AccessLevels {
@@ -1062,10 +1106,10 @@ impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet {
     reachable_set
 });
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use traits::Vtable::*;
 
@@ -1084,10 +1128,10 @@ for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableImplData {
             impl_def_id,
@@ -1100,10 +1144,10 @@ for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'gc
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableAutoImplData {
             trait_def_id,
@@ -1114,10 +1158,10 @@ for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'gcx>
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableObjectData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableObjectData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableObjectData {
             upcast_trait_ref,
@@ -1130,10 +1174,10 @@ for traits::VtableObjectData<'gcx, N> where N: HashStable<StableHashingContext<'
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableBuiltinData<N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableBuiltinData<N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableBuiltinData {
             ref nested,
@@ -1142,10 +1186,10 @@ for traits::VtableBuiltinData<N> where N: HashStable<StableHashingContext<'gcx>>
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableClosureData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableClosureData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableClosureData {
             closure_def_id,
@@ -1158,10 +1202,10 @@ for traits::VtableClosureData<'gcx, N> where N: HashStable<StableHashingContext<
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableFnPointerData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableFnPointerData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableFnPointerData {
             fn_ty,
@@ -1172,10 +1216,10 @@ for traits::VtableFnPointerData<'gcx, N> where N: HashStable<StableHashingContex
     }
 }
 
-impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableGeneratorData {
             closure_def_id,
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 909904b4fc3..8a899a35ecb 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -394,10 +394,10 @@ impl LintLevelMap {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for LintLevelMap {
+impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let LintLevelMap {
             ref sets,
diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs
index f0285d6a937..9a394e52481 100644
--- a/src/librustc/macros.rs
+++ b/src/librustc/macros.rs
@@ -73,10 +73,10 @@ macro_rules! __impl_stable_hash_field {
 #[macro_export]
 macro_rules! impl_stable_hash_for {
     (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
-        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $enum_name {
+        impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 use $enum_name::*;
                 ::std::mem::discriminant(self).hash_stable(__ctx, __hasher);
@@ -92,10 +92,10 @@ macro_rules! impl_stable_hash_for {
         }
     };
     (struct $struct_name:path { $($field:ident),* }) => {
-        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $struct_name {
+        impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name {
                     $(ref $field),*
@@ -106,10 +106,10 @@ macro_rules! impl_stable_hash_for {
         }
     };
     (tuple_struct $struct_name:path { $($field:ident),* }) => {
-        impl<'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'tcx>> for $struct_name {
+        impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
-                                                  __ctx: &mut $crate::ich::StableHashingContext<'tcx>,
+                                                  __ctx: &mut $crate::ich::StableHashingContext<'a>,
                                                   __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<W>) {
                 let $struct_name (
                     $(ref $field),*
@@ -125,11 +125,11 @@ macro_rules! impl_stable_hash_for {
 macro_rules! impl_stable_hash_for_spanned {
     ($T:path) => (
 
-        impl<'tcx> HashStable<StableHashingContext<'tcx>> for ::syntax::codemap::Spanned<$T>
+        impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ::syntax::codemap::Spanned<$T>
         {
             #[inline]
             fn hash_stable<W: StableHasherResult>(&self,
-                                                  hcx: &mut StableHashingContext<'tcx>,
+                                                  hcx: &mut StableHashingContext<'a>,
                                                   hasher: &mut StableHasher<W>) {
                 self.node.hash_stable(hcx, hasher);
                 self.span.hash_stable(hcx, hasher);
diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs
index 380f79361e2..6f5791ed5d7 100644
--- a/src/librustc/middle/borrowck.rs
+++ b/src/librustc/middle/borrowck.rs
@@ -20,9 +20,9 @@ pub struct BorrowCheckResult {
     pub used_mut_nodes: FxHashSet<HirId>,
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for BorrowCheckResult {
+impl<'a> HashStable<StableHashingContext<'a>> for BorrowCheckResult {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let BorrowCheckResult {
             ref used_mut_nodes,
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 812ee0dc72f..c73930553cd 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1488,9 +1488,9 @@ pub fn provide(providers: &mut Providers) {
     };
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ScopeTree {
+impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ScopeTree {
             root_body,
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index efc2f647cfd..45cb70d0070 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -35,9 +35,9 @@ impl serialize::Decodable for Cache {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Cache {
+impl<'a> HashStable<StableHashingContext<'a>> for Cache {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut StableHashingContext<'gcx>,
+                                          _: &mut StableHashingContext<'a>,
                                           _: &mut StableHasher<W>) {
         // do nothing
     }
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 394b3d96a4f..c395be549a3 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -200,6 +200,8 @@ pub struct UndefMask {
     len: u64,
 }
 
+impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
+
 impl UndefMask {
     pub fn new(size: u64) -> Self {
         let mut m = UndefMask {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 9e9ba516203..8da3a125d3f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1877,7 +1877,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
     }
 }
 
-fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
+pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
     use ty::TypeVariants::*;
     use rustc_const_math::ConstFloat;
     match (value, &ty.sty) {
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index d8eac2b4159..d01059a3e01 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -41,9 +41,9 @@ impl<'tcx> MonoItem<'tcx> {
     }
 }
 
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for MonoItem<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                           hcx: &mut StableHashingContext<'tcx>,
+                                           hcx: &mut StableHashingContext<'a>,
                                            hasher: &mut StableHasher<W>) {
         ::std::mem::discriminant(self).hash_stable(hcx, hasher);
 
@@ -171,9 +171,9 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 }
 
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for CodegenUnit<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                           hcx: &mut StableHashingContext<'tcx>,
+                                           hcx: &mut StableHashingContext<'a>,
                                            hasher: &mut StableHasher<W>) {
         let CodegenUnit {
             ref items,
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 157614f847a..437369400ed 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -179,10 +179,10 @@ impl_stable_hash_for!(enum self::OutputType {
     DepInfo
 });
 
-impl<'tcx> ToStableHashKey<StableHashingContext<'tcx>> for OutputType {
+impl<'a, 'tcx> ToStableHashKey<StableHashingContext<'a>> for OutputType {
     type KeyType = OutputType;
     #[inline]
-    fn to_stable_hash_key(&self, _: &StableHashingContext<'tcx>) -> Self::KeyType {
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> Self::KeyType {
         *self
     }
 }
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index dbf15ad1707..f8b895177f3 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -391,9 +391,9 @@ pub fn ancestors(tcx: TyCtxt,
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Children {
+impl<'a> HashStable<StableHashingContext<'a>> for Children {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let Children {
             ref nonblanket_impls,
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index bf75afcfa1a..3ec3f665db9 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -676,9 +676,9 @@ impl<'tcx> TypeckTables<'tcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for TypeckTables<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TypeckTables {
             local_id_root,
@@ -1366,7 +1366,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.cstore.crate_data_as_rc_any(cnum)
     }
 
-    pub fn create_stable_hashing_context(self) -> StableHashingContext<'gcx> {
+    pub fn create_stable_hashing_context(self) -> StableHashingContext<'a> {
         let krate = self.dep_graph.with_ignore(|| self.gcx.hir.krate());
 
         StableHashingContext::new(self.sess,
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 97c259e6bf3..93d8a4d979d 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -154,12 +154,12 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
     }
 }
 
-impl<'gcx, D> HashStable<StableHashingContext<'gcx>> for SimplifiedTypeGen<D>
+impl<'a, 'gcx, D> HashStable<StableHashingContext<'a>> for SimplifiedTypeGen<D>
     where D: Copy + Debug + Ord + Eq + Hash +
-             HashStable<StableHashingContext<'gcx>>,
+             HashStable<StableHashingContext<'a>>,
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 35d8fb2a67a..79f01a32cd9 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -2369,9 +2369,9 @@ impl<'a, 'tcx> TyLayout<'tcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Variants {
+impl<'a> HashStable<StableHashingContext<'a>> for Variants {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::Variants::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -2405,9 +2405,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Variants {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for FieldPlacement {
+impl<'a> HashStable<StableHashingContext<'a>> for FieldPlacement {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::FieldPlacement::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -2428,9 +2428,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FieldPlacement {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi {
+impl<'a> HashStable<StableHashingContext<'a>> for Abi {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::Abi::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -2455,9 +2455,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for Scalar {
+impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let Scalar { value, valid_range: RangeInclusive { start, end } } = *self;
         value.hash_stable(hcx, hasher);
@@ -2498,10 +2498,10 @@ impl_stable_hash_for!(struct ::ty::layout::Size {
     raw
 });
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for LayoutError<'gcx>
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LayoutError<'gcx>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         use ty::layout::LayoutError::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f9071cff78f..2c7ec5155a6 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -80,7 +80,7 @@ pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
 pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local};
-pub use self::context::{Lift, TypeckTables};
+pub use self::context::{Lift, TypeckTables, InterpretInterner};
 
 pub use self::instance::{Instance, InstanceDef};
 
@@ -529,9 +529,9 @@ impl<'tcx> TyS<'tcx> {
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TyS<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::TyS<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TyS {
             ref sty,
@@ -1440,11 +1440,11 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> {
     }
 }
 
-impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for ParamEnvAnd<'gcx, T>
-    where T: HashStable<StableHashingContext<'gcx>>
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ParamEnvAnd<'gcx, T>
+    where T: HashStable<StableHashingContext<'a>>
 {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ParamEnvAnd {
             ref param_env,
@@ -1545,9 +1545,9 @@ impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef {
 impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
 
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for AdtDef {
+impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         thread_local! {
             static CACHE: RefCell<FxHashMap<usize, Fingerprint>> =
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 62d3c8dc87d..32f0d3384c4 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -186,9 +186,9 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     })
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for TraitImpls {
+impl<'a> HashStable<StableHashingContext<'a>> for TraitImpls {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let TraitImpls {
             ref blanket_impls,
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index ce94e4f912f..593f08e90bb 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -227,9 +227,9 @@ pub struct TraitImpls {
     pub impls: LazySeq<DefIndex>,
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for TraitImpls {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let TraitImpls {
             trait_id: (krate, def_index),
@@ -310,9 +310,9 @@ pub enum EntryKind<'tcx> {
     AssociatedConst(AssociatedContainer, u8),
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for EntryKind<'gcx> {
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 30c70ac30a7..067041b14f5 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -20,12 +20,10 @@ use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::bitvec::BitVector;
-use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
-use rustc::mir::interpret::{Value, PrimVal};
-use rustc::hir::RangeEnd;
+use rustc::hir::{RangeEnd, Mutability};
 use syntax_pos::Span;
 use std::cmp::Ordering;
 
@@ -297,76 +295,86 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             TestKind::Eq { value, ty } => {
                 let tcx = self.hir.tcx();
                 let mut val = Operand::Copy(place.clone());
-
-                let bytes = match value.val {
-                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(p))) => {
-                        let is_array_ptr = ty
-                            .builtin_deref(true, ty::NoPreference)
-                            .and_then(|t| t.ty.builtin_index())
-                            .map_or(false, |t| t == self.hir.tcx().types.u8);
-                        if is_array_ptr {
-                            self.hir
-                                .tcx()
-                                .interpret_interner
-                                .borrow()
-                                .get_alloc(p.alloc_id)
-                                .map(|alloc| &alloc.bytes[..])
-                        } else {
-                            None
-                        }
-                    },
-                    _ => None,
-                };
-                // If we're using b"..." as a pattern, we need to insert an
-                // unsizing coercion, as the byte string has the type &[u8; N].
-                //
-                // We want to do this even when the scrutinee is a reference to an
-                // array, so we can call `<[u8]>::eq` rather than having to find an
-                // `<[u8; N]>::eq`.
-                let expect = if let Some(bytes) = bytes {
-                    let tcx = self.hir.tcx();
-
-                    // Unsize the place to &[u8], too, if necessary.
-                    if let ty::TyRef(region, mt) = ty.sty {
-                        if let ty::TyArray(_, _) = mt.ty.sty {
-                            ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
-                            let val_slice = self.temp(ty, test.span);
-                            self.cfg.push_assign(block, source_info, &val_slice,
-                                                 Rvalue::Cast(CastKind::Unsize, val, ty));
-                            val = Operand::Move(val_slice);
-                        }
-                    }
-
-                    assert!(ty.is_slice());
-
-                    let array_ty = tcx.mk_array(tcx.types.u8, bytes.len() as u64);
-                    let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
-                    let array = self.literal_operand(test.span, array_ref, Literal::Value {
-                        value
-                    });
-
-                    let val = self.to_slice_operand(block, source_info, val);
-                    let slice = self.to_slice_operand(block, source_info, array);
-                    (slice, val)
-                } else {
-                    (self.literal_operand(test.span, ty, Literal::Value {
-                        value
-                    }), val)
-                };
-
-                // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
+                let mut expect = self.literal_operand(test.span, ty, Literal::Value {
+                    value
+                });
+                // Use PartialEq::eq instead of BinOp::Eq
+                // (the binop can only handle primitives)
                 let fail = self.cfg.start_new_block();
-                let str_or_bytestr = ty
-                    .builtin_deref(true, ty::NoPreference)
-                    .and_then(|tam| match tam.ty.sty {
-                        ty::TyStr => Some(tam.ty),
-                        ty::TySlice(inner) if inner == self.hir.tcx().types.u8 => Some(tam.ty),
+                if !ty.is_scalar() {
+                    // If we're using b"..." as a pattern, we need to insert an
+                    // unsizing coercion, as the byte string has the type &[u8; N].
+                    //
+                    // We want to do this even when the scrutinee is a reference to an
+                    // array, so we can call `<[u8]>::eq` rather than having to find an
+                    // `<[u8; N]>::eq`.
+                    let unsize = |ty: Ty<'tcx>| match ty.sty {
+                        ty::TyRef(region, tam) => match tam.ty.sty {
+                            ty::TyArray(inner_ty, n) => Some((region, inner_ty, n)),
+                            _ => None,
+                        },
                         _ => None,
-                    });
-                if let Some(ty) = str_or_bytestr {
+                    };
+                    let opt_ref_ty = unsize(ty);
+                    let opt_ref_test_ty = unsize(value.ty);
+                    let mut place = place.clone();
+                    match (opt_ref_ty, opt_ref_test_ty) {
+                        // nothing to do, neither is an array
+                        (None, None) => {},
+                        (Some((region, elem_ty, _)), _) |
+                        (None, Some((region, elem_ty, _))) => {
+                            let tcx = self.hir.tcx();
+                            // make both a slice
+                            ty = tcx.mk_imm_ref(region, tcx.mk_slice(elem_ty));
+                            if opt_ref_ty.is_some() {
+                                place = self.temp(ty, test.span);
+                                self.cfg.push_assign(block, source_info, &place,
+                                                    Rvalue::Cast(CastKind::Unsize, val, ty));
+                            }
+                            if opt_ref_test_ty.is_some() {
+                                let array = self.literal_operand(
+                                    test.span,
+                                    value.ty,
+                                    Literal::Value {
+                                        value
+                                    },
+                                );
+
+                                let slice = self.temp(ty, test.span);
+                                self.cfg.push_assign(block, source_info, &slice,
+                                                    Rvalue::Cast(CastKind::Unsize, array, ty));
+                                expect = Operand::Move(slice);
+                            }
+                        },
+                    }
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);
 
+                    // take the argument by reference
+                    let region_scope = self.topmost_scope();
+                    let region = self.hir.tcx().mk_region(ty::ReScope(region_scope));
+                    let tam = ty::TypeAndMut {
+                        ty,
+                        mutbl: Mutability::MutImmutable,
+                    };
+                    let ref_ty = self.hir.tcx().mk_ref(region, tam);
+
+                    // let lhs_ref_place = &lhs;
+                    let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, place.clone());
+                    let lhs_ref_place = self.temp(ref_ty, test.span);
+                    self.cfg.push_assign(block, source_info, &lhs_ref_place, ref_rvalue);
+                    let val = Operand::Move(lhs_ref_place);
+
+                    // let rhs_place = rhs;
+                    let rhs_place = self.temp(ty, test.span);
+                    self.cfg.push_assign(block, source_info, &rhs_place, Rvalue::Use(expect));
+
+                    // let rhs_ref_place = &rhs_place;
+                    let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, rhs_place);
+                    let rhs_ref_place = self.temp(ref_ty, test.span);
+                    self.cfg.push_assign(block, source_info, &rhs_ref_place, ref_rvalue);
+                    let expect = Operand::Move(rhs_ref_place);
+
                     let bool_ty = self.hir.bool_ty();
                     let eq_result = self.temp(bool_ty, test.span);
                     let eq_block = self.cfg.start_new_block();
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index f2533276645..2000ebea25d 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -72,36 +72,6 @@ fn foo(x: Option<String>) {
 ```
 "##,
 
-E0003: r##"
-#### Note: this error code is no longer emitted by the compiler.
-
-Not-a-Number (NaN) values cannot be compared for equality and hence can never
-match the input to a match expression. So, the following will not compile:
-
-```compile_fail
-const NAN: f32 = 0.0 / 0.0;
-
-let number = 0.1f32;
-
-match number {
-    NAN => { /* ... */ },
-    _ => {}
-}
-```
-
-To match against NaN values, you should instead use the `is_nan()` method in a
-guard, like so:
-
-```
-let number = 0.1f32;
-
-match number {
-    x if x.is_nan() => { /* ... */ }
-    _ => {}
-}
-```
-"##,
-
 E0004: r##"
 This error indicates that the compiler cannot guarantee a matching pattern for
 one or more possible inputs to a match expression. Guaranteed matches are
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 1b4cbecab3b..2dcad403f52 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -19,6 +19,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     instance: Instance<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
+    span: Span,
 ) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>> {
     debug!("mk_borrowck_eval_cx: {:?}", instance);
     let param_env = tcx.param_env(instance.def_id());
@@ -27,7 +28,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
     // insert a stack frame so any queries have the correct substs
     ecx.push_stack_frame(
         instance,
-        mir.span,
+        span,
         mir,
         Place::undef(),
         StackPopCleanup::None,
@@ -65,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
-            ecx.report(&mut err, true);
+            ecx.report(&mut err, true, None);
             None
         }
     }
@@ -80,7 +81,7 @@ pub fn eval_body<'a, 'tcx>(
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
-            ecx.report(&mut err, true);
+            ecx.report(&mut err, true, None);
             None
         }
     }
@@ -483,7 +484,7 @@ pub fn const_eval_provider<'a, 'tcx>(
         })
     }).map_err(|mut err| {
         if tcx.is_static(def_id).is_some() {
-            ecx.report(&mut err, true);
+            ecx.report(&mut err, true, None);
         }
         ConstEvalErr {
             kind: err.into(),
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 7d2b83e9217..7dafe846a33 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -10,7 +10,7 @@ use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
-use syntax::codemap::{self, DUMMY_SP};
+use syntax::codemap::{self, DUMMY_SP, Span};
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
     GlobalId, Value, Pointer, PrimVal, PrimValKind,
@@ -464,7 +464,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             StackPopCleanup::MarkStatic(mutable) => {
                 if let Place::Ptr { ptr, .. } = frame.return_place {
                     // FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions
-                    self.memory.mark_static_initalized(
+                    self.memory.mark_static_initialized(
                         ptr.to_ptr()?.alloc_id,
                         mutable,
                     )?
@@ -1572,7 +1572,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         Ok(())
     }
 
-    pub fn report(&self, e: &mut EvalError, as_err: bool) {
+    pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
         if let EvalErrorKind::TypeckError = e.kind {
             return;
         }
@@ -1608,11 +1608,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         }
         if let Some(frame) = self.stack().last() {
             let block = &frame.mir.basic_blocks()[frame.block];
-            let span = if frame.stmt < block.statements.len() {
+            let span = explicit_span.unwrap_or_else(|| if frame.stmt < block.statements.len() {
                 block.statements[frame.stmt].source_info.span
             } else {
                 block.terminator().source_info.span
-            };
+            });
+            trace!("reporting const eval failure at {:?}", span);
             let node_id = self
                 .stack()
                 .iter()
@@ -1634,6 +1635,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             let mut last_span = None;
             for &Frame { instance, span, .. } in self.stack().iter().rev() {
                 // make sure we don't emit frames that are duplicates of the previous
+                if explicit_span == Some(span) {
+                    continue;
+                }
                 if let Some(last) = last_span {
                     if last == span {
                         continue;
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 5ee84e0e02c..eebd48f7bb9 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -520,18 +520,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
             // do not go into statics
             None  => Ok(()),
             // just locals and machine allocs
-            Some(_) => self.mark_static_initalized(alloc, mutability),
+            Some(_) => self.mark_static_initialized(alloc, mutability),
         }
     }
 
     /// mark an allocation as static and initialized, either mutable or not
-    pub fn mark_static_initalized(
+    pub fn mark_static_initialized(
         &mut self,
         alloc_id: AllocId,
         mutability: Mutability,
     ) -> EvalResult<'tcx> {
         trace!(
-            "mark_static_initalized {:?}, mutability: {:?}",
+            "mark_static_initialized {:?}, mutability: {:?}",
             alloc_id,
             mutability
         );
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 4dc0879c85d..03b215fa0b8 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -52,7 +52,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             }
         }
 
-        self.memory.mark_static_initalized(
+        self.memory.mark_static_initialized(
             vtable.alloc_id,
             Mutability::Immutable,
         )?;
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index e27e7c72473..6079e1929b5 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -23,7 +23,7 @@ use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
 use std::collections::VecDeque;
 use transform::{MirPass, MirSource};
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::Span;
 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
 use rustc::ty::subst::Substs;
 
@@ -147,7 +147,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for InstCombineVisitor<'a, 'tcx> {
             TerminatorKind::SwitchInt { discr: value, .. } |
             TerminatorKind::Yield { value, .. } |
             TerminatorKind::Assert { cond: value, .. } => {
-                if let Some((new, ty, span)) = self.optimizations.const_prop.remove(&location) {
+                if let Some((new, ty, span)) = self.optimizations.terminators.remove(&block) {
                     let new = self.tcx.mk_const(ty::Const {
                         val: ConstVal::Value(new),
                         ty,
@@ -190,13 +190,13 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
         }
     }
 
-    fn eval_constant(&mut self, c: &Constant<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
         if let Some(&val) = self.optimizations.constants.get(c) {
             return Some(val);
         }
         match c.literal {
             Literal::Value { value } => match value.val {
-                ConstVal::Value(v) => Some((v, value.ty, span)),
+                ConstVal::Value(v) => Some((v, value.ty, c.span)),
                 ConstVal::Unevaluated(did, substs) => {
                     let param_env = self.tcx.param_env(self.source.def_id);
                     let span = self.tcx.def_span(did);
@@ -230,10 +230,9 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
                     instance,
                     promoted: Some(index),
                 };
-                let span = self.tcx.def_span(self.source.def_id);
                 let param_env = self.tcx.param_env(self.source.def_id);
                 let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, param_env)?;
-                let val = (value, ty, span);
+                let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 self.optimizations.constants.insert(c.clone(), val);
                 Some(val)
@@ -241,9 +240,9 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
         }
     }
 
-    fn eval_operand(&mut self, op: &Operand<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
         match *op {
-            Operand::Constant(ref c) => self.eval_constant(c, span),
+            Operand::Constant(ref c) => self.eval_constant(c),
             Operand::Move(ref place) | Operand::Copy(ref place) => match *place {
                 Place::Local(loc) => self.optimizations.places.get(&loc).cloned(),
                 // FIXME(oli-obk): field and index projections
@@ -253,13 +252,13 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
         }
     }
 
-    fn simplify_operand(&mut self, op: &Operand<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn simplify_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
         match *op {
             Operand::Constant(ref c) => match c.literal {
                 Literal::Value { .. } => None,
-                _ => self.eval_operand(op, span),
+                _ => self.eval_operand(op),
             },
-            _ => self.eval_operand(op, span),
+            _ => self.eval_operand(op),
         }
     }
 
@@ -270,7 +269,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
         span: Span,
     ) -> Option<Const<'tcx>> {
         match *rvalue {
-            Rvalue::Use(ref op) => self.simplify_operand(op, span),
+            Rvalue::Use(ref op) => self.simplify_operand(op),
             Rvalue::Repeat(..) |
             Rvalue::Ref(..) |
             Rvalue::Cast(..) |
@@ -300,15 +299,15 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
                 }
                 let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
                 let instance = Instance::new(self.source.def_id, substs);
-                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir).unwrap();
+                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
-                let val = self.eval_operand(arg, span)?;
+                let val = self.eval_operand(arg)?;
                 let prim = ecx.value_to_primval(ValTy { value: val.0, ty: val.1 }).ok()?;
                 let kind = ecx.ty_to_primval_kind(val.1).ok()?;
                 match unary_op(op, prim, kind) {
                     Ok(val) => Some((Value::ByVal(val), place_ty, span)),
                     Err(mut err) => {
-                        ecx.report(&mut err, false);
+                        ecx.report(&mut err, false, Some(span));
                         None
                     },
                 }
@@ -316,8 +315,8 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
                 trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
-                let left = self.eval_operand(left, span)?;
-                let right = self.eval_operand(right, span)?;
+                let left = self.eval_operand(left)?;
+                let right = self.eval_operand(right)?;
                 let def_id = if self.tcx.is_closure(self.source.def_id) {
                     self.tcx.closure_base_def_id(self.source.def_id)
                 } else {
@@ -331,7 +330,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
                 }
                 let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
                 let instance = Instance::new(self.source.def_id, substs);
-                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir).unwrap();
+                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
                 let l = ecx.value_to_primval(ValTy { value: left.0, ty: left.1 }).ok()?;
                 let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
@@ -351,7 +350,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
                                     kind: EvalErrorKind::OverflowingMath,
                                     backtrace: None,
                                 };
-                                ecx.report(&mut err, false);
+                                ecx.report(&mut err, false, Some(span));
                                 return None;
                             }
                             Value::ByVal(val)
@@ -359,7 +358,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
                         Some((val, place_ty, span))
                     },
                     Err(mut err) => {
-                        ecx.report(&mut err, false);
+                        ecx.report(&mut err, false, Some(span));
                         None
                     },
                 }
@@ -500,7 +499,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
     ) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
-        self.eval_constant(constant, DUMMY_SP);
+        self.eval_constant(constant);
     }
 
     fn visit_statement(
@@ -514,7 +513,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
             let place_ty = place
                 .ty(&self.mir.local_decls, self.tcx)
                 .to_ty(self.tcx);
-            let span = self.mir.source_info(location).span;
+            let span = statement.source_info.span;
             if let Some(value) = self.const_prop(rval, place_ty, span) {
                 self.optimizations.const_prop.insert(location, value);
                 if let Place::Local(local) = *place {
@@ -554,17 +553,16 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
 
     fn visit_terminator_kind(
         &mut self,
-        _block: BasicBlock,
+        block: BasicBlock,
         kind: &TerminatorKind<'tcx>,
-        location: Location,
+        _location: Location,
     ) {
-        let span = self.mir.source_info(location).span;
         match kind {
             TerminatorKind::SwitchInt { discr: value, .. } |
             TerminatorKind::Yield { value, .. } |
             TerminatorKind::Assert { cond: value, .. } => {
-                if let Some(value) = self.simplify_operand(value, span) {
-                    self.optimizations.const_prop.insert(location, value);
+                if let Some(value) = self.simplify_operand(value) {
+                    self.optimizations.terminators.insert(block, value);
                 }
             }
             // FIXME: do this optimization for function calls
@@ -578,6 +576,8 @@ struct OptimizationList<'tcx> {
     and_stars: FxHashSet<Location>,
     arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
     const_prop: FxHashMap<Location, Const<'tcx>>,
+    /// Terminators that get their Operand(s) turned into constants.
+    terminators: FxHashMap<BasicBlock, Const<'tcx>>,
     places: FxHashMap<Local, Const<'tcx>>,
     constants: FxHashMap<Constant<'tcx>, Const<'tcx>>,
 }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 9d1f7631375..652069ab7c1 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -265,6 +265,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         generator::StateTransform,
 
         instcombine::InstCombine,
+        simplify_branches::SimplifyBranches::new("after-const-prop"),
         deaggregator::Deaggregator,
         copy_prop::CopyPropagation,
         remove_noop_landing_pads::RemoveNoopLandingPads,
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index da10fcffb4c..cc5af9489b4 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -128,7 +128,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
             _ => None,
         };
         if let Some((def_id, args)) = check {
-            if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() {
+            if Some(def_id) == self.fx.cx.tcx.lang_items().box_free_fn() {
                 // box_free(x) shares with `drop x` the property that it
                 // is not guaranteed to be statically dominated by the
                 // definition of x, so x must always be in an alloca.
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 6d2f9c6c97f..cc344fdf063 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -204,7 +204,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     let (otherwise, targets) = targets.split_last().unwrap();
                     let switch = bx.switch(discr.immediate(),
                                             llblock(self, *otherwise), values.len());
-                    let switch_llty = bcx.ccx.layout_of(switch_ty).immediate_llvm_type(bcx.ccx);
+                    let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
                     for (&value, target) in values.iter().zip(targets) {
                         let llval = C_uint_big(switch_llty, value);
                         let llbb = llblock(self, *target);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 5050628b024..be5cb311b9c 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -29,7 +29,7 @@ use type_of::LayoutLlvmExt;
 use type_::Type;
 
 use super::super::callee;
-use super::MirContext;
+use super::FunctionCx;
 
 fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> {
     match t.sty {
@@ -135,15 +135,15 @@ pub fn const_scalar_checked_binop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-pub fn primval_to_llvm(ccx: &CrateContext,
+pub fn primval_to_llvm(cx: &CodegenCx,
                        cv: PrimVal,
                        scalar: &Scalar,
                        llty: Type) -> ValueRef {
-    let bits = if scalar.is_bool() { 1 } else { scalar.value.size(ccx).bits() };
+    let bits = if scalar.is_bool() { 1 } else { scalar.value.size(cx).bits() };
     match cv {
-        PrimVal::Undef => C_undef(Type::ix(ccx, bits)),
+        PrimVal::Undef => C_undef(Type::ix(cx, bits)),
         PrimVal::Bytes(b) => {
-            let llval = C_uint_big(Type::ix(ccx, bits), b);
+            let llval = C_uint_big(Type::ix(cx, bits), b);
             if scalar.value == layout::Pointer {
                 unsafe { llvm::LLVMConstIntToPtr(llval, llty.to_ref()) }
             } else {
@@ -151,28 +151,28 @@ pub fn primval_to_llvm(ccx: &CrateContext,
             }
         },
         PrimVal::Ptr(ptr) => {
-            let interpret_interner = ccx.tcx().interpret_interner.borrow();
+            let interpret_interner = cx.tcx.interpret_interner.borrow();
             if let Some(fn_instance) = interpret_interner.get_fn(ptr.alloc_id) {
-                callee::get_fn(ccx, fn_instance)
+                callee::get_fn(cx, fn_instance)
             } else {
                 let static_ = interpret_interner.get_corresponding_static_def_id(ptr.alloc_id);
                 let base_addr = if let Some(def_id) = static_ {
-                    assert!(ccx.tcx().is_static(def_id).is_some());
-                    consts::get_static(ccx, def_id)
+                    assert!(cx.tcx.is_static(def_id).is_some());
+                    consts::get_static(cx, def_id)
                 } else if let Some(alloc) = interpret_interner.get_alloc(ptr.alloc_id) {
-                    let init = global_initializer(ccx, alloc);
+                    let init = global_initializer(cx, alloc);
                     if alloc.mutable {
-                        consts::addr_of_mut(ccx, init, alloc.align, "byte_str")
+                        consts::addr_of_mut(cx, init, alloc.align, "byte_str")
                     } else {
-                        consts::addr_of(ccx, init, alloc.align, "byte_str")
+                        consts::addr_of(cx, init, alloc.align, "byte_str")
                     }
                 } else {
                     bug!("missing allocation {:?}", ptr.alloc_id);
                 };
 
                 let llval = unsafe { llvm::LLVMConstInBoundsGEP(
-                    consts::bitcast(base_addr, Type::i8p(ccx)),
-                    &C_usize(ccx, ptr.offset),
+                    consts::bitcast(base_addr, Type::i8p(cx)),
+                    &C_usize(cx, ptr.offset),
                     1,
                 ) };
                 if scalar.value != layout::Pointer {
@@ -185,9 +185,9 @@ pub fn primval_to_llvm(ccx: &CrateContext,
     }
 }
 
-pub fn global_initializer(ccx: &CrateContext, alloc: &Allocation) -> ValueRef {
+pub fn global_initializer(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
-    let layout = ccx.data_layout();
+    let layout = cx.data_layout();
     let pointer_size = layout.pointer_size.bytes() as usize;
 
     let mut next_offset = 0;
@@ -195,28 +195,28 @@ pub fn global_initializer(ccx: &CrateContext, alloc: &Allocation) -> ValueRef {
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
         if offset > next_offset {
-            llvals.push(C_bytes(ccx, &alloc.bytes[next_offset..offset]));
+            llvals.push(C_bytes(cx, &alloc.bytes[next_offset..offset]));
         }
         let ptr_offset = read_target_uint(
             layout.endian,
             &alloc.bytes[offset..(offset + pointer_size)],
         ).expect("global_initializer: could not read relocation pointer") as u64;
         llvals.push(primval_to_llvm(
-            ccx,
+            cx,
             PrimVal::Ptr(MemoryPointer { alloc_id, offset: ptr_offset }),
             &Scalar {
                 value: layout::Primitive::Pointer,
                 valid_range: 0..=!0
             },
-            Type::i8p(ccx)
+            Type::i8p(cx)
         ));
         next_offset = offset + pointer_size;
     }
     if alloc.bytes.len() >= next_offset {
-        llvals.push(C_bytes(ccx, &alloc.bytes[next_offset ..]));
+        llvals.push(C_bytes(cx, &alloc.bytes[next_offset ..]));
     }
 
-    C_struct(ccx, &llvals, true)
+    C_struct(cx, &llvals, true)
 }
 
 pub fn trans_static_initializer<'a, 'tcx>(
@@ -224,39 +224,39 @@ pub fn trans_static_initializer<'a, 'tcx>(
     def_id: DefId)
     -> Result<ValueRef, ConstEvalErr<'tcx>>
 {
-    let instance = ty::Instance::mono(ccx.tcx(), def_id);
+    let instance = ty::Instance::mono(cx.tcx, def_id);
     let cid = GlobalId {
         instance,
         promoted: None
     };
     let param_env = ty::ParamEnv::empty(traits::Reveal::All);
-    ccx.tcx().const_eval(param_env.and(cid))?;
+    cx.tcx.const_eval(param_env.and(cid))?;
 
-    let alloc_id = ccx
-        .tcx()
+    let alloc_id = cx
+        .tcx
         .interpret_interner
         .borrow()
         .get_cached(def_id)
         .expect("global not cached");
 
-    let alloc = ccx
-        .tcx()
+    let alloc = cx
+        .tcx
         .interpret_interner
         .borrow()
         .get_alloc(alloc_id)
         .expect("miri allocation never successfully created");
-    Ok(global_initializer(ccx, alloc))
+    Ok(global_initializer(cx, alloc))
 }
 
 impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     fn const_to_miri_value(
         &mut self,
-        bcx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
     ) -> Result<MiriValue, ConstEvalErr<'tcx>> {
         match constant.val {
             ConstVal::Unevaluated(def_id, ref substs) => {
-                let tcx = bcx.tcx();
+                let tcx = bx.tcx();
                 let param_env = ty::ParamEnv::empty(traits::Reveal::All);
                 let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
                 let cid = GlobalId {
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     promoted: None,
                 };
                 let c = tcx.const_eval(param_env.and(cid))?;
-                self.const_to_miri_value(bcx, c)
+                self.const_to_miri_value(bx, c)
             },
             ConstVal::Value(miri_val) => Ok(miri_val),
         }
@@ -272,7 +272,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
     pub fn mir_constant_to_miri_value(
         &mut self,
-        bcx: &Builder<'a, 'tcx>,
+        bx: &Builder<'a, 'tcx>,
         constant: &mir::Constant<'tcx>,
     ) -> Result<MiriValue, ConstEvalErr<'tcx>> {
         match constant.literal {
@@ -282,22 +282,22 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     instance: self.instance,
                     promoted: Some(index),
                 };
-                bcx.tcx().const_eval(param_env.and(cid))
+                bx.tcx().const_eval(param_env.and(cid))
             }
             mir::Literal::Value { value } => {
                 Ok(self.monomorphize(&value))
             }
-        }.and_then(|c| self.const_to_miri_value(bcx, c))
+        }.and_then(|c| self.const_to_miri_value(bx, c))
     }
 
     // Old version of trans_constant now used just for SIMD shuffle
     pub fn remove_me_shuffle_indices(&mut self,
-                                      bcx: &Builder<'a, 'tcx>,
+                                      bx: &Builder<'a, 'tcx>,
                                       constant: &mir::Constant<'tcx>)
                                       -> (ValueRef, Ty<'tcx>)
     {
-        let layout = bcx.ccx.layout_of(constant.ty);
-        self.mir_constant_to_miri_value(bcx, constant)
+        let layout = bx.cx.layout_of(constant.ty);
+        self.mir_constant_to_miri_value(bx, constant)
             .and_then(|c| {
                 let llval = match c {
                     MiriValue::ByVal(val) => {
@@ -305,7 +305,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                             layout::Abi::Scalar(ref x) => x,
                             _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
                         };
-                        primval_to_llvm(bcx.ccx, val, scalar, layout.immediate_llvm_type(bcx.ccx))
+                        primval_to_llvm(bx.cx, val, scalar, layout.immediate_llvm_type(bx.cx))
                     },
                     MiriValue::ByValPair(a_val, b_val) => {
                         let (a_scalar, b_scalar) = match layout.abi {
@@ -313,18 +313,18 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                             _ => bug!("from_const: invalid ByValPair layout: {:#?}", layout)
                         };
                         let a_llval = primval_to_llvm(
-                            bcx.ccx,
+                            bx.cx,
                             a_val,
                             a_scalar,
-                            layout.scalar_pair_element_llvm_type(bcx.ccx, 0),
+                            layout.scalar_pair_element_llvm_type(bx.cx, 0),
                         );
                         let b_llval = primval_to_llvm(
-                            bcx.ccx,
+                            bx.cx,
                             b_val,
                             b_scalar,
-                            layout.scalar_pair_element_llvm_type(bcx.ccx, 1),
+                            layout.scalar_pair_element_llvm_type(bx.cx, 1),
                         );
-                        C_struct(bcx.ccx, &[a_llval, b_llval], false)
+                        C_struct(bx.cx, &[a_llval, b_llval], false)
                     },
                     MiriValue::ByRef(..) => {
                         let field_ty = constant.ty.builtin_index().unwrap();
@@ -334,7 +334,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                         };
                         let values: Result<Vec<ValueRef>, _> = (0..fields).map(|field| {
                             let field = const_val_field(
-                                bcx.tcx(),
+                                bx.tcx(),
                                 ty::ParamEnv::empty(traits::Reveal::All),
                                 self.instance,
                                 None,
@@ -344,29 +344,29 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                             )?;
                             match field.val {
                                 ConstVal::Value(MiriValue::ByVal(prim)) => {
-                                    let layout = bcx.ccx.layout_of(field_ty);
+                                    let layout = bx.cx.layout_of(field_ty);
                                     let scalar = match layout.abi {
                                         layout::Abi::Scalar(ref x) => x,
                                         _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
                                     };
                                     Ok(primval_to_llvm(
-                                        bcx.ccx, prim, scalar,
-                                        layout.immediate_llvm_type(bcx.ccx),
+                                        bx.cx, prim, scalar,
+                                        layout.immediate_llvm_type(bx.cx),
                                     ))
                                 },
                                 other => bug!("simd shuffle field {:?}, {}", other, constant.ty),
                             }
                         }).collect();
-                        C_struct(bcx.ccx, &values?, false)
+                        C_struct(bx.cx, &values?, false)
                     },
                 };
                 Ok((llval, constant.ty))
             })
             .unwrap_or_else(|e| {
-                e.report(bcx.tcx(), constant.span, "shuffle_indices");
+                e.report(bx.tcx(), constant.span, "shuffle_indices");
                 // We've errored, so we don't have to produce working code.
                 let ty = self.monomorphize(&constant.ty);
-                let llty = bcx.ccx.layout_of(ty).llvm_type(bcx.ccx);
+                let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
                 (C_undef(llty), ty)
             })
     }
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 01cf324124c..a66528858e1 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -92,14 +92,14 @@ impl<'a, 'tcx> OperandRef<'tcx> {
         }
     }
 
-    pub fn from_const(bcx: &Builder<'a, 'tcx>,
+    pub fn from_const(bx: &Builder<'a, 'tcx>,
                       miri_val: MiriValue,
                       ty: ty::Ty<'tcx>)
                       -> Result<OperandRef<'tcx>, ConstEvalErr<'tcx>> {
-        let layout = bcx.ccx.layout_of(ty);
+        let layout = bx.cx.layout_of(ty);
 
         if layout.is_zst() {
-            return Ok(OperandRef::new_zst(bcx.ccx, layout));
+            return Ok(OperandRef::new_zst(bx.cx, layout));
         }
 
         let val = match miri_val {
@@ -109,10 +109,10 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                     _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
                 };
                 let llval = primval_to_llvm(
-                    bcx.ccx,
+                    bx.cx,
                     x,
                     scalar,
-                    layout.immediate_llvm_type(bcx.ccx),
+                    layout.immediate_llvm_type(bx.cx),
                 );
                 OperandValue::Immediate(llval)
             },
@@ -122,16 +122,16 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                     _ => bug!("from_const: invalid ByValPair layout: {:#?}", layout)
                 };
                 let a_llval = primval_to_llvm(
-                    bcx.ccx,
+                    bx.cx,
                     a,
                     a_scalar,
-                    layout.scalar_pair_element_llvm_type(bcx.ccx, 0),
+                    layout.scalar_pair_element_llvm_type(bx.cx, 0),
                 );
                 let b_llval = primval_to_llvm(
-                    bcx.ccx,
+                    bx.cx,
                     b,
                     b_scalar,
-                    layout.scalar_pair_element_llvm_type(bcx.ccx, 1),
+                    layout.scalar_pair_element_llvm_type(bx.cx, 1),
                 );
                 OperandValue::Pair(a_llval, b_llval)
             },
@@ -141,12 +141,12 @@ impl<'a, 'tcx> OperandRef<'tcx> {
                     valid_range: 0..=!0
                 };
                 let ptr = primval_to_llvm(
-                    bcx.ccx,
+                    bx.cx,
                     ptr.into_inner_primval(),
                     &scalar,
-                    layout.llvm_type(bcx.ccx).ptr_to(),
+                    layout.llvm_type(bx.cx).ptr_to(),
                 );
-                return Ok(PlaceRef::new_sized(ptr, layout, align).load(bcx));
+                return Ok(PlaceRef::new_sized(ptr, layout, align).load(bx));
             },
         };
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b9e4ce661d0..2372153963a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -34,6 +34,7 @@ use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime as rl;
 use rustc::ty::fold::TypeFolder;
 use rustc::middle::lang_items;
+use rustc::mir::interpret::GlobalId;
 use rustc::hir::{self, HirVec};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -2510,14 +2511,24 @@ impl Clean<Type> for hir::Ty {
                         ty: cx.tcx.types.usize
                     })
                 });
-                let n = if let ConstVal::Unevaluated(def_id, _) = n.val {
-                    if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
-                        print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
-                    } else {
-                        inline::print_inlined_const(cx, def_id)
-                    }
-                } else {
-                    format!("{:?}", n)
+                let n = match n.val {
+                    ConstVal::Unevaluated(def_id, _) => {
+                        if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
+                            print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
+                        } else {
+                            inline::print_inlined_const(cx, def_id)
+                        }
+                    },
+                    ConstVal::Value(val) => {
+                        let mut s = String::new();
+                        ::rustc::mir::print_miri_value(val, n.ty, &mut s).unwrap();
+                        // array lengths are obviously usize
+                        if s.ends_with("usize") {
+                            let n = s.len() - "usize".len();
+                            s.truncate(n);
+                        }
+                        s
+                    },
                 };
                 Array(box ty.clean(cx), n)
             },
@@ -2645,14 +2656,24 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                         n = new_n;
                     }
                 };
-                let n = if let ConstVal::Unevaluated(def_id, _) = n.val {
-                    if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
-                        print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
-                    } else {
-                        inline::print_inlined_const(cx, def_id)
-                    }
-                } else {
-                    format!("{:?}", n)
+                let n = match n.val {
+                    ConstVal::Unevaluated(def_id, _) => {
+                        if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
+                            print_const_expr(cx, cx.tcx.hir.body_owned_by(node_id))
+                        } else {
+                            inline::print_inlined_const(cx, def_id)
+                        }
+                    },
+                    ConstVal::Value(val) => {
+                        let mut s = String::new();
+                        ::rustc::mir::print_miri_value(val, n.ty, &mut s).unwrap();
+                        // array lengths are obviously usize
+                        if s.ends_with("usize") {
+                            let n = s.len() - "usize".len();
+                            s.truncate(n);
+                        }
+                        s
+                    },
                 };
                 Array(box ty.clean(cx), n)
             }
diff --git a/src/test/compile-fail/const-err2.rs b/src/test/compile-fail/const-err2.rs
index a0648993aac..09983f17926 100644
--- a/src/test/compile-fail/const-err2.rs
+++ b/src/test/compile-fail/const-err2.rs
@@ -19,10 +19,12 @@ fn black_box<T>(_: T) {
 fn main() {
     let a = -std::i8::MIN;
     //~^ ERROR const_err
-    //~| ERROR const_err
     let b = 200u8 + 200u8 + 200u8;
+    //~^ ERROR const_err
     let c = 200u8 * 4;
+    //~^ ERROR const_err
     let d = 42u8 - (42u8 + 1);
+    //~^ ERROR const_err
     let _e = [5u8][1];
     black_box(a);
     black_box(b);
diff --git a/src/test/compile-fail/const-err3.rs b/src/test/compile-fail/const-err3.rs
index 636537d1df2..9656af60024 100644
--- a/src/test/compile-fail/const-err3.rs
+++ b/src/test/compile-fail/const-err3.rs
@@ -18,9 +18,10 @@ fn black_box<T>(_: T) {
 fn main() {
     let b = 200u8 + 200u8 + 200u8;
     //~^ ERROR const_err
-    //~| ERROR const_err
     let c = 200u8 * 4;
+    //~^ ERROR const_err
     let d = 42u8 - (42u8 + 1);
+    //~^ ERROR const_err
     let _e = [5u8][1];
     black_box(b);
     black_box(c);
diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/ctfe/references.rs
new file mode 100644
index 00000000000..ad7dbeb79c7
--- /dev/null
+++ b/src/test/run-pass/ctfe/references.rs
@@ -0,0 +1,34 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const FOO: &[u8] = b"foo";
+const BAR: &[u8] = &[1, 2, 3];
+
+const BOO: &i32 = &42;
+
+fn main() {
+    match &[1u8, 2, 3] as &[u8] {
+        FOO => panic!("a"),
+        BAR => println!("b"),
+        _ => panic!("c"),
+    }
+
+    match b"foo" as &[u8] {
+        FOO => println!("a"),
+        BAR => panic!("b"),
+        _ => panic!("c"),
+    }
+
+    match &43 {
+        &42 => panic!(),
+        BOO => panic!(),
+        _ => println!("d"),
+    }
+}