about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-08-07 14:43:43 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-08-11 12:11:38 +0200
commit7f2423eede51cc622420356988777db2473a0be2 (patch)
tree15338bec5c4128dd527c9a1cc6becae7911c9454
parent783ccc443b88884a10eed564e0fdc3c1e6f974a4 (diff)
downloadrust-7f2423eede51cc622420356988777db2473a0be2.tar.gz
rust-7f2423eede51cc622420356988777db2473a0be2.zip
Use ItemLocalId as key for node_types, node_substs, and adjustments in TypeckTables.
-rw-r--r--src/librustc/hir/lowering.rs9
-rw-r--r--src/librustc/hir/mod.rs1
-rw-r--r--src/librustc/ich/hcx.rs14
-rw-r--r--src/librustc/ich/impls_hir.rs1
-rw-r--r--src/librustc/ich/impls_ty.rs10
-rw-r--r--src/librustc/ich/mod.rs2
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs10
-rw-r--r--src/librustc/infer/error_reporting/util.rs2
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs9
-rw-r--r--src/librustc/middle/intrinsicck.rs2
-rw-r--r--src/librustc/middle/mem_categorization.rs19
-rw-r--r--src/librustc/ty/context.rs42
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs4
-rw-r--r--src/librustc_const_eval/check_match.rs6
-rw-r--r--src/librustc_const_eval/eval.rs2
-rw-r--r--src/librustc_const_eval/pattern.rs18
-rw-r--r--src/librustc_lint/builtin.rs12
-rw-r--r--src/librustc_lint/types.rs6
-rw-r--r--src/librustc_mir/build/mod.rs3
-rw-r--r--src/librustc_mir/hair/cx/block.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs19
-rw-r--r--src/librustc_passes/consts.rs6
-rw-r--r--src/librustc_privacy/lib.rs12
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs17
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs22
-rw-r--r--src/librustc_typeck/check/mod.rs67
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/regionck.rs70
-rw-r--r--src/librustc_typeck/check/upvar.rs8
-rw-r--r--src/librustc_typeck/check/writeback.rs72
-rw-r--r--src/librustc_typeck/collect.rs3
35 files changed, 282 insertions, 208 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 27048a71454..356d8209ce5 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -904,8 +904,10 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
         P(hir::Local {
-            id: self.lower_node_id(l.id).node_id,
+            id: node_id,
+            hir_id,
             ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
             pat: self.lower_pat(&l.pat),
             init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
@@ -2675,11 +2677,14 @@ impl<'a> LoweringContext<'a> {
                     pat: P<hir::Pat>,
                     source: hir::LocalSource)
                     -> hir::Stmt {
+        let LoweredNodeId { node_id, hir_id } = self.next_id();
+
         let local = P(hir::Local {
             pat,
             ty: None,
             init: ex,
-            id: self.next_id().node_id,
+            id: node_id,
+            hir_id,
             span: sp,
             attrs: ThinVec::new(),
             source,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index a2be74b5522..1831814b0f4 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -901,6 +901,7 @@ pub struct Local {
     /// Initializer expression to set the value, if any
     pub init: Option<P<Expr>>,
     pub id: NodeId,
+    pub hir_id: HirId,
     pub span: Span,
     pub attrs: ThinVec<Attribute>,
     pub source: LocalSource,
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 8ce1b39d934..218483232d6 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -14,7 +14,7 @@ use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
 use ty;
-use util::nodemap::NodeMap;
+use util::nodemap::{NodeMap, ItemLocalMap};
 
 use std::hash as std_hash;
 use std::collections::{HashMap, HashSet, BTreeMap};
@@ -358,6 +358,18 @@ pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>(
     });
 }
 
+pub fn hash_stable_itemlocalmap<'a, 'tcx, 'gcx, V, W>(
+    hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+    hasher: &mut StableHasher<W>,
+    map: &ItemLocalMap<V>)
+    where V: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>,
+          W: StableHasherResult,
+{
+    hash_stable_hashmap(hcx, hasher, map, |_, local_id| {
+        *local_id
+    });
+}
+
 
 pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>(
     hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index fca70de704f..4c70816c0b8 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -506,6 +506,7 @@ impl_stable_hash_for!(struct hir::Local {
     ty,
     init,
     id,
+    hir_id,
     span,
     attrs,
     source
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 37ef7e8cbfa..ab505141880 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -638,12 +638,10 @@ for ty::TypeckTables<'gcx> {
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            ich::hash_stable_hashmap(hcx, hasher, type_dependent_defs, |_, item_local_id| {
-                *item_local_id
-            });
-            ich::hash_stable_nodemap(hcx, hasher, node_types);
-            ich::hash_stable_nodemap(hcx, hasher, node_substs);
-            ich::hash_stable_nodemap(hcx, hasher, adjustments);
+            ich::hash_stable_itemlocalmap(hcx, hasher, type_dependent_defs);
+            ich::hash_stable_itemlocalmap(hcx, hasher, node_types);
+            ich::hash_stable_itemlocalmap(hcx, hasher, node_substs);
+            ich::hash_stable_itemlocalmap(hcx, hasher, adjustments);
             ich::hash_stable_nodemap(hcx, hasher, pat_binding_modes);
             ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
                 let ty::UpvarId {
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index 5b238090850..dcf84be0eeb 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -14,7 +14,7 @@ pub use self::fingerprint::Fingerprint;
 pub use self::caching_codemap_view::CachingCodemapView;
 pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
                     hash_stable_hashset, hash_stable_nodemap,
-                    hash_stable_btreemap};
+                    hash_stable_btreemap, hash_stable_itemlocalmap};
 mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index a684881c091..22d9a9e313b 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hir::{self, Local, Pat, Body};
+use hir::{self, Local, Pat, Body, HirId};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::InferCtxt;
 use infer::type_variable::TypeVariableOrigin;
 use ty::{self, Ty, TyInfer, TyVar};
-
-use syntax::ast::NodeId;
 use syntax_pos::Span;
 
 struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
@@ -26,7 +24,7 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
-    fn node_matches_type(&mut self, node_id: NodeId) -> bool {
+    fn node_matches_type(&mut self, node_id: HirId) -> bool {
         let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
             tables.borrow().node_id_to_type_opt(node_id)
         });
@@ -56,7 +54,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
     }
 
     fn visit_local(&mut self, local: &'gcx Local) {
-        if self.found_local_pattern.is_none() && self.node_matches_type(local.id) {
+        if self.found_local_pattern.is_none() && self.node_matches_type(local.hir_id) {
             self.found_local_pattern = Some(&*local.pat);
         }
         intravisit::walk_local(self, local);
@@ -64,7 +62,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
 
     fn visit_body(&mut self, body: &'gcx Body) {
         for argument in &body.arguments {
-            if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) {
+            if self.found_arg_pattern.is_none() && self.node_matches_type(argument.hir_id) {
                 self.found_arg_pattern = Some(&*argument.pat);
             }
         }
diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs
index 14fe8e699c7..c8f78367420 100644
--- a/src/librustc/infer/error_reporting/util.rs
+++ b/src/librustc/infer/error_reporting/util.rs
@@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             .iter()
                             .enumerate()
                             .filter_map(|(index, arg)| {
-                                let ty = tables.borrow().node_id_to_type(arg.id);
+                                let ty = tables.borrow().node_id_to_type(arg.hir_id);
                                 let mut found_anon_region = false;
                                 let new_arg_ty = self.tcx
                                     .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 4cf27981e1b..0cca5690c01 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -121,7 +121,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                                   pats: &[codemap::Spanned<hir::FieldPat>]) {
 
 
-        let variant = match self.tables.node_id_to_type(lhs.id).sty {
+        let variant = match self.tables.node_id_to_type(lhs.hir_id).sty {
             ty::TyAdt(adt, _) => adt.variant_of_def(def),
             _ => span_bug!(lhs.span, "non-ADT in struct pattern")
         };
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 80abe87470c..b44f1c7da73 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -296,7 +296,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         debug!("consume_body(body={:?})", body);
 
         for arg in &body.arguments {
-            let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id));
+            let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.hir_id));
 
             let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
             let arg_cmt = self.mc.cat_rvalue(
@@ -826,7 +826,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 let bm = *mc.tables.pat_binding_modes.get(&pat.id).expect("missing binding mode");
 
                 // pat_ty: the type of the binding being produced.
-                let pat_ty = return_if_err!(mc.node_ty(pat.id));
+                let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
@@ -923,8 +923,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                         -> mc::McResult<mc::cmt<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
-        let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap();
-        let var_ty = self.mc.node_ty(var_id)?;
+        let var_node_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap();
+        let var_hir_id = self.tcx().hir.node_to_hir_id(var_node_id);
+        let var_ty = self.mc.node_ty(var_hir_id)?;
         self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
     }
 }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 83278bd88e9..0a4e5094cde 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -152,7 +152,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
         };
         if let Def::Fn(did) = def {
             if self.def_id_is_transmute(did) {
-                let typ = self.tables.node_id_to_type(expr.id);
+                let typ = self.tables.node_id_to_type(expr.hir_id);
                 let sig = typ.fn_sig(self.tcx);
                 let from = sig.inputs().skip_binder()[0];
                 let to = *sig.output().skip_binder();
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index c6773250bde..7a949cf38b3 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -435,7 +435,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     }
 
     fn resolve_type_vars_or_error(&self,
-                                  id: ast::NodeId,
+                                  id: hir::HirId,
                                   ty: Option<Ty<'tcx>>)
                                   -> McResult<Ty<'tcx>> {
         match ty {
@@ -451,26 +451,30 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             // FIXME
             None if self.is_tainted_by_errors() => Err(()),
             None => {
+                let id = self.tcx.hir.definitions().find_node_for_hir_id(id);
                 bug!("no type for node {}: {} in mem_categorization",
                      id, self.tcx.hir.node_to_string(id));
             }
         }
     }
 
-    pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id))
+    pub fn node_ty(&self,
+                   hir_id: hir::HirId)
+                   -> McResult<Ty<'tcx>> {
+        self.resolve_type_vars_or_error(hir_id,
+                                        self.tables.node_id_to_type_opt(hir_id))
     }
 
     pub fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr))
+        self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_opt(expr))
     }
 
     pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
-        self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr))
+        self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_adjusted_opt(expr))
     }
 
     fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
-        let base_ty = self.node_ty(pat.id)?;
+        let base_ty = self.node_ty(pat.hir_id)?;
         // FIXME (Issue #18207): This code detects whether we are
         // looking at a `ref x`, and if so, figures out what the type
         // *being borrowed* is.  But ideally we would put in a more
@@ -714,7 +718,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
         let upvar_id = ty::UpvarId { var_id,
                                      closure_expr_id: fn_node_id };
-        let var_ty = self.node_ty(var_id)?;
+        let var_hir_id = self.tcx.hir.node_to_hir_id(var_id);
+        let var_ty = self.node_ty(var_hir_id)?;
 
         // Mutability of original variable itself
         let var_mutbl = MutabilityCategory::from_local(self.tcx, self.tables, var_id);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 46bb13c89ba..528fb4e2e7f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -57,7 +57,7 @@ use std::ops::Deref;
 use std::iter;
 use std::rc::Rc;
 use syntax::abi;
-use syntax::ast::{self, Name, NodeId};
+use syntax::ast::{self, Name};
 use syntax::attr;
 use syntax::codemap::MultiSpan;
 use syntax::symbol::{Symbol, keywords};
@@ -219,15 +219,15 @@ pub struct TypeckTables<'tcx> {
     /// Stores the types for various nodes in the AST.  Note that this table
     /// is not guaranteed to be populated until after typeck.  See
     /// typeck::check::fn_ctxt for details.
-    pub node_types: NodeMap<Ty<'tcx>>,
+    pub node_types: ItemLocalMap<Ty<'tcx>>,
 
     /// Stores the type parameters which were substituted to obtain the type
     /// of this node.  This only applies to nodes that refer to entities
     /// parameterized by type parameters, such as generic fns, types, or
     /// other items.
-    pub node_substs: NodeMap<&'tcx Substs<'tcx>>,
+    pub node_substs: ItemLocalMap<&'tcx Substs<'tcx>>,
 
-    pub adjustments: NodeMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
 
     // Stores the actual binding mode for all instances of hir::BindingAnnotation.
     pub pat_binding_modes: NodeMap<BindingMode>,
@@ -278,9 +278,9 @@ impl<'tcx> TypeckTables<'tcx> {
         TypeckTables {
             local_id_root,
             type_dependent_defs: ItemLocalMap(),
-            node_types: FxHashMap(),
-            node_substs: NodeMap(),
-            adjustments: NodeMap(),
+            node_types: ItemLocalMap(),
+            node_substs: ItemLocalMap(),
+            adjustments: ItemLocalMap(),
             pat_binding_modes: NodeMap(),
             upvar_capture_map: FxHashMap(),
             closure_tys: NodeMap(),
@@ -305,32 +305,37 @@ impl<'tcx> TypeckTables<'tcx> {
         }
     }
 
-    pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
+    pub fn node_id_to_type(&self, id: hir::HirId) -> Ty<'tcx> {
         match self.node_id_to_type_opt(id) {
             Some(ty) => ty,
             None => {
                 bug!("node_id_to_type: no type for node `{}`",
-                     tls::with(|tcx| tcx.hir.node_to_string(id)))
+                    tls::with(|tcx| {
+                        let id = tcx.hir.definitions().find_node_for_hir_id(id);
+                        tcx.hir.node_to_string(id)
+                    }))
             }
         }
     }
 
-    pub fn node_id_to_type_opt(&self, id: NodeId) -> Option<Ty<'tcx>> {
-        self.node_types.get(&id).cloned()
+    pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+        self.validate_hir_id(id);
+        self.node_types.get(&id.local_id).cloned()
     }
 
-    pub fn node_substs(&self, id: NodeId) -> &'tcx Substs<'tcx> {
-        self.node_substs.get(&id).cloned().unwrap_or(Substs::empty())
+    pub fn node_substs(&self, id: hir::HirId) -> &'tcx Substs<'tcx> {
+        self.validate_hir_id(id);
+        self.node_substs.get(&id.local_id).cloned().unwrap_or(Substs::empty())
     }
 
     // Returns the type of a pattern as a monotype. Like @expr_ty, this function
     // doesn't provide type parameter substitutions.
     pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> {
-        self.node_id_to_type(pat.id)
+        self.node_id_to_type(pat.hir_id)
     }
 
     pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> {
-        self.node_id_to_type_opt(pat.id)
+        self.node_id_to_type_opt(pat.hir_id)
     }
 
     // Returns the type of an expression as a monotype.
@@ -344,16 +349,17 @@ impl<'tcx> TypeckTables<'tcx> {
     // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
     // instead of "fn(ty) -> T with T = isize".
     pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> {
-        self.node_id_to_type(expr.id)
+        self.node_id_to_type(expr.hir_id)
     }
 
     pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
-        self.node_id_to_type_opt(expr.id)
+        self.node_id_to_type_opt(expr.hir_id)
     }
 
     pub fn expr_adjustments(&self, expr: &hir::Expr)
                             -> &[ty::adjustment::Adjustment<'tcx>] {
-        self.adjustments.get(&expr.id).map_or(&[], |a| &a[..])
+        self.validate_hir_id(expr.hir_id);
+        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
     }
 
     /// Returns the type of `expr`, considering any `Adjustment`
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 3d669aa81df..7a89d1f09d3 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -155,7 +155,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     }
 
     fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) {
-        let ty = self.bccx.tables.node_id_to_type(id);
+        let ty = self.bccx
+                     .tables
+                     .node_id_to_type(self.bccx.tcx.hir.node_to_hir_id(id));
         gather_moves::gather_decl(self.bccx, &self.move_data, id, ty);
     }
 }
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index a3f8aae472c..0d92bff02b1 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -188,7 +188,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
 
             // Then, if the match has no arms, check whether the scrutinee
             // is uninhabited.
-            let pat_ty = self.tables.node_id_to_type(scrut.id);
+            let pat_ty = self.tables.node_id_to_type(scrut.hir_id);
             let module = self.tcx.hir.get_module_parent(scrut.id);
             if inlined_arms.is_empty() {
                 let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
@@ -217,7 +217,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
                 .flat_map(|arm| &arm.0)
                 .map(|pat| vec![pat.0])
                 .collect();
-            let scrut_ty = self.tables.node_id_to_type(scrut.id);
+            let scrut_ty = self.tables.node_id_to_type(scrut.hir_id);
             check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
         })
     }
@@ -494,7 +494,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                 let bm = *cx.tables.pat_binding_modes.get(&p.id).expect("missing binding mode");
                 match bm {
                     ty::BindByValue(..) => {
-                        let pat_ty = cx.tables.node_id_to_type(p.id);
+                        let pat_ty = cx.tables.node_id_to_type(p.hir_id);
                         if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index cce511daf8a..c0a050cb6b4 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -275,7 +275,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         }
       }
       hir::ExprPath(ref qpath) => {
-        let substs = cx.tables.node_substs(e.id).subst(tcx, cx.substs);
+        let substs = cx.tables.node_substs(e.hir_id).subst(tcx, cx.substs);
           match cx.tables.qpath_def(qpath, e.hir_id) {
               Def::Const(def_id) |
               Def::AssociatedConst(def_id) => {
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index 30183ca2daf..bad9895420a 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -303,7 +303,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
     }
 
     pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
-        let mut ty = self.tables.node_id_to_type(pat.id);
+        let mut ty = self.tables.node_id_to_type(pat.hir_id);
 
         let kind = match pat.node {
             PatKind::Wild => PatternKind::Wild,
@@ -321,7 +321,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             }
 
             PatKind::Path(ref qpath) => {
-                return self.lower_path(qpath, (pat.id, pat.hir_id), pat.id, pat.span);
+                return self.lower_path(qpath, pat.hir_id, pat.id, pat.span);
             }
 
             PatKind::Ref(ref subpattern, _) |
@@ -330,7 +330,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             }
 
             PatKind::Slice(ref prefix, ref slice, ref suffix) => {
-                let ty = self.tables.node_id_to_type(pat.id);
+                let ty = self.tables.node_id_to_type(pat.hir_id);
                 match ty.sty {
                     ty::TyRef(_, mt) =>
                         PatternKind::Deref {
@@ -355,7 +355,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             }
 
             PatKind::Tuple(ref subpatterns, ddpos) => {
-                let ty = self.tables.node_id_to_type(pat.id);
+                let ty = self.tables.node_id_to_type(pat.hir_id);
                 match ty.sty {
                     ty::TyTuple(ref tys, _) => {
                         let subpatterns =
@@ -376,7 +376,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
             PatKind::Binding(_, def_id, ref ident, ref sub) => {
                 let id = self.tcx.hir.as_local_node_id(def_id).unwrap();
-                let var_ty = self.tables.node_id_to_type(pat.id);
+                let var_ty = self.tables.node_id_to_type(pat.hir_id);
                 let region = match var_ty.sty {
                     ty::TyRef(r, _) => Some(r),
                     _ => None,
@@ -590,12 +590,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
     fn lower_path(&mut self,
                   qpath: &hir::QPath,
-                  (id, hir_id): (ast::NodeId, hir::HirId),
+                  id: hir::HirId,
                   pat_id: ast::NodeId,
                   span: Span)
                   -> Pattern<'tcx> {
         let ty = self.tables.node_id_to_type(id);
-        let def = self.tables.qpath_def(qpath, hir_id);
+        let def = self.tables.qpath_def(qpath, id);
         let kind = match def {
             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 let substs = self.tables.node_substs(id);
@@ -695,7 +695,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                     hir::ExprPath(ref qpath) => qpath,
                     _ => bug!()
                 };
-                let ty = self.tables.node_id_to_type(callee.id);
+                let ty = self.tables.node_id_to_type(callee.hir_id);
                 let def = self.tables.qpath_def(qpath, callee.hir_id);
                 match def {
                     Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
@@ -755,7 +755,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             }
 
             hir::ExprPath(ref qpath) => {
-                return self.lower_path(qpath, (expr.id, expr.hir_id), pat_id, span);
+                return self.lower_path(qpath, expr.hir_id, pat_id, span);
             }
 
             _ => self.lower_lit(expr)
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 85ec606e87e..56c0fa7b2ad 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
     }
 
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
-        let ty = cx.tables.node_id_to_type(e.id);
+        let ty = cx.tables.node_id_to_type(e.hir_id);
         self.check_heap_type(cx, e.span, ty);
     }
 }
@@ -934,9 +934,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
 
             // Check for method calls and overloaded operators.
             if cx.tables.is_method_call(expr) {
-                let local_id = cx.tcx.hir.definitions().node_to_hir_id(id).local_id;
-                let def_id = cx.tables.type_dependent_defs[&local_id].def_id();
-                let substs = cx.tables.node_substs(id);
+                let hir_id = cx.tcx.hir.definitions().node_to_hir_id(id);
+                let def_id = cx.tables.type_dependent_defs[&hir_id.local_id].def_id();
+                let substs = cx.tables.node_substs(hir_id);
                 if method_call_refers_to_method(cx, method, def_id, substs, id) {
                     return true;
                 }
@@ -952,7 +952,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                     };
                     match def {
                         Def::Method(def_id) => {
-                            let substs = cx.tables.node_substs(callee.id);
+                            let substs = cx.tables.node_substs(callee.hir_id);
                             method_call_refers_to_method(cx, method, def_id, substs, id)
                         }
                         _ => false,
@@ -1188,7 +1188,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
-                let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx);
+                let sig = cx.tables.node_id_to_type(expr.hir_id).fn_sig(cx.tcx);
                 let from = sig.inputs().skip_binder()[0];
                 let to = *sig.output().skip_binder();
                 return Some((&from.sty, &to.sty));
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index aca98df9cc9..cdf09967960 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 }
 
                 if binop.node.is_shift() {
-                    let opt_ty_bits = match cx.tables.node_id_to_type(l.id).sty {
+                    let opt_ty_bits = match cx.tables.node_id_to_type(l.hir_id).sty {
                         ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
                         ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
                         _ => None,
@@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 }
             }
             hir::ExprLit(ref lit) => {
-                match cx.tables.node_id_to_type(e.id).sty {
+                match cx.tables.node_id_to_type(e.hir_id).sty {
                     ty::TyInt(t) => {
                         match lit.node {
                             ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
@@ -285,7 +285,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
             // Normalize the binop so that the literal is always on the RHS in
             // the comparison
             let norm_binop = if swap { rev_binop(binop) } else { binop };
-            match cx.tables.node_id_to_type(expr.id).sty {
+            match cx.tables.node_id_to_type(expr.hir_id).sty {
                 ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i128 = match lit.node {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 3353fb9a5b4..66817fda5b7 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -202,7 +202,8 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              closure_expr_id: ast::NodeId,
                              body_id: hir::BodyId)
                              -> Ty<'tcx> {
-    let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id);
+    let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
+    let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
 
     let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
     let region = ty::ReFree(ty::FreeRegion {
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index c91326f6d87..fa54925c6e7 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -95,7 +95,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    block: &'tcx hir::Block)
                                    -> ExprRef<'tcx> {
-    let block_ty = cx.tables().node_id_to_type(block.id);
+    let block_ty = cx.tables().node_id_to_type(block.hir_id);
     let temp_lifetime = cx.region_maps.temporary_scope(block.id);
     let expr = Expr {
         ty: block_ty,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 3effc29d67e..ea9a19c8378 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -217,7 +217,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     None
                 };
                 if let Some((adt_def, index)) = adt_data {
-                    let substs = cx.tables().node_substs(fun.id);
+                    let substs = cx.tables().node_substs(fun.hir_id);
                     let field_refs = args.iter()
                         .enumerate()
                         .map(|(idx, e)| {
@@ -236,7 +236,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     }
                 } else {
                     ExprKind::Call {
-                        ty: cx.tables().node_id_to_type(fun.id),
+                        ty: cx.tables().node_id_to_type(fun.hir_id),
                         fun: fun.to_ref(),
                         args: args.to_ref(),
                     }
@@ -582,7 +582,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let (def_id, substs) = custom_callee.unwrap_or_else(|| {
         cx.tables().validate_hir_id(expr.hir_id);
         (cx.tables().type_dependent_defs[&expr.hir_id.local_id].def_id(),
-         cx.tables().node_substs(expr.id))
+         cx.tables().node_substs(expr.hir_id))
     });
     Expr {
         temp_lifetime: temp_lifetime,
@@ -620,7 +620,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                      expr: &'tcx hir::Expr,
                                      def: Def)
                                      -> ExprKind<'tcx> {
-    let substs = cx.tables().node_substs(expr.id);
+    let substs = cx.tables().node_substs(expr.hir_id);
     match def {
         // A regular function, constructor function or a constant.
         Def::Fn(def_id) |
@@ -642,7 +642,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         Def::StructCtor(def_id, CtorKind::Const) |
         Def::VariantCtor(def_id, CtorKind::Const) => {
-            match cx.tables().node_id_to_type(expr.id).sty {
+            match cx.tables().node_id_to_type(expr.hir_id).sty {
                 // A unit struct/variant which is used as a value.
                 // We return a completely different ExprKind here to account for this special case.
                 ty::TyAdt(adt_def, substs) => {
@@ -684,10 +684,12 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                    id_var,
                    index,
                    closure_expr_id);
-            let var_ty = cx.tables().node_id_to_type(id_var);
+            let var_ty = cx.tables()
+                           .node_id_to_type(cx.tcx.hir.node_to_hir_id(id_var));
 
             // FIXME free regions in closures are not right
-            let closure_ty = cx.tables().node_id_to_type(closure_expr_id);
+            let closure_ty = cx.tables()
+                               .node_id_to_type(cx.tcx.hir.node_to_hir_id(closure_expr_id));
 
             // FIXME we're just hard-coding the idea that the
             // signature will be &self or &mut self and hence will
@@ -879,7 +881,8 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     };
     let upvar_capture = cx.tables().upvar_capture(upvar_id);
     let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id);
-    let var_ty = cx.tables().node_id_to_type(id_var);
+    let var_ty = cx.tables()
+                   .node_id_to_type(cx.tcx.hir.node_to_hir_id(id_var));
     let captured_var = Expr {
         temp_lifetime: temp_lifetime,
         ty: var_ty,
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index b3a1509972a..c06ae721f36 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -219,7 +219,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
         let outer = self.promotable;
         self.promotable = true;
 
-        let node_ty = self.tables.node_id_to_type(ex.id);
+        let node_ty = self.tables.node_id_to_type(ex.hir_id);
         check_expr(self, ex, node_ty);
         check_adjustments(self, ex);
 
@@ -297,7 +297,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             v.promotable = false;
         }
         hir::ExprUnary(op, ref inner) => {
-            match v.tables.node_id_to_type(inner.id).sty {
+            match v.tables.node_id_to_type(inner.hir_id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op == hir::UnDeref);
 
@@ -307,7 +307,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
         hir::ExprBinary(op, ref lhs, _) => {
-            match v.tables.node_id_to_type(lhs.id).sty {
+            match v.tables.node_id_to_type(lhs.hir_id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
                             op.node == hir::BiLe || op.node == hir::BiLt ||
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index c1cab0cc8f7..1c5e528d887 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -639,7 +639,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
     }
 
     // Take node ID of an expression or pattern and check its type for privacy.
-    fn check_expr_pat_type(&mut self, id: ast::NodeId, span: Span) -> bool {
+    fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
         self.span = span;
         if let Some(ty) = self.tables.node_id_to_type_opt(id) {
             if ty.visit_with(self) {
@@ -649,7 +649,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
         if self.tables.node_substs(id).visit_with(self) {
             return true;
         }
-        if let Some(adjustments) = self.tables.adjustments.get(&id) {
+        if let Some(adjustments) = self.tables.adjustments.get(&id.local_id) {
             for adjustment in adjustments {
                 if adjustment.target.visit_with(self) {
                     return true;
@@ -735,14 +735,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     // Check types of expressions
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
-        if self.check_expr_pat_type(expr.id, expr.span) {
+        if self.check_expr_pat_type(expr.hir_id, expr.span) {
             // Do not check nested expressions if the error already happened.
             return;
         }
         match expr.node {
             hir::ExprAssign(.., ref rhs) | hir::ExprMatch(ref rhs, ..) => {
                 // Do not report duplicate errors for `x = y` and `match x { ... }`.
-                if self.check_expr_pat_type(rhs.id, rhs.span) {
+                if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
                     return;
                 }
             }
@@ -783,7 +783,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     // Check types of patterns
     fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
-        if self.check_expr_pat_type(pattern.id, pattern.span) {
+        if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
             // Do not check nested patterns if the error already happened.
             return;
         }
@@ -793,7 +793,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
 
     fn visit_local(&mut self, local: &'tcx hir::Local) {
         if let Some(ref init) = local.init {
-            if self.check_expr_pat_type(init.id, init.span) {
+            if self.check_expr_pat_type(init.hir_id, init.span) {
                 // Do not report duplicate errors for `let x = y`.
                 return;
             }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 4740f9a0d5a..af816473033 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -345,7 +345,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
             for &(id, ref p, ..) in &collector.collected_paths {
-                let typ = match self.save_ctxt.tables.node_types.get(&id) {
+                let hir_id = self.tcx.hir.node_to_hir_id(id);
+                let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
@@ -893,7 +894,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         match p.node {
             PatKind::Struct(ref _path, ref fields, _) => {
                 // FIXME do something with _path?
-                let adt = match self.save_ctxt.tables.node_id_to_type_opt(p.id) {
+                let hir_id = self.tcx.hir.node_to_hir_id(p.id);
+                let adt = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                     Some(ty) => ty.ty_adt_def().unwrap(),
                     None => {
                         visit::walk_pat(self, p);
@@ -935,7 +937,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
             };
-            let typ = match self.save_ctxt.tables.node_types.get(&id) {
+            let hir_id = self.tcx.hir.node_to_hir_id(id);
+            let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                 Some(typ) => {
                     let typ = typ.to_string();
                     if !value.is_empty() {
@@ -1466,8 +1469,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                     } else {
                         "<mutable>".to_string()
                     };
-                    let typ = self.save_ctxt.tables.node_types
-                                  .get(&id).map(|t| t.to_string()).unwrap_or(String::new());
+                    let hir_id = self.tcx.hir.node_to_hir_id(id);
+                    let typ = self.save_ctxt
+                                  .tables
+                                  .node_id_to_type_opt(hir_id)
+                                  .map(|t| t.to_string())
+                                  .unwrap_or(String::new());
                     value.push_str(": ");
                     value.push_str(&typ);
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index eaff8e7b8ac..e1ced048870 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -323,7 +323,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         };
 
-        self.write_ty(pat.id, ty);
+        self.write_ty(pat.hir_id, ty);
 
         // (*) In most of the cases above (literals and constants being
         // the exception), we relate types using strict equality, evewn
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index cdf1c3b235b..460e2858b22 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -314,7 +314,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                            TupleArgumentsFlag::TupleArguments,
                                                            expected);
 
-        self.write_method_call((call_expr.id, call_expr.hir_id), method_callee);
+        self.write_method_call(call_expr.hir_id, method_callee);
         output_type
     }
 }
@@ -364,7 +364,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
                 adjustments.extend(autoref);
                 fcx.apply_adjustments(self.callee_expr, adjustments);
 
-                fcx.write_method_call((self.call_expr.id, self.call_expr.hir_id),
+                fcx.write_method_call(self.call_expr.hir_id,
                                       method_callee);
             }
             None => {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 934a4f9b296..428938eae82 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -844,7 +844,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // First try to coerce the new expression to the type of the previous ones,
         // but only if the new expression has no coercion already applied to it.
         let mut first_error = None;
-        if !self.tables.borrow().adjustments.contains_key(&new.id) {
+        if !self.tables.borrow().adjustments.contains_key(&new.hir_id.local_id) {
             let result = self.commit_if_ok(|_| coerce.coerce(new_ty, prev_ty));
             match result {
                 Ok(ok) => {
@@ -866,7 +866,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     Adjustment { kind: Adjust::Deref(_), .. },
                     Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }
                 ] => {
-                    match self.node_ty(expr.id).sty {
+                    match self.node_ty(expr.hir_id).sty {
                         ty::TyRef(_, mt_orig) => {
                             // Reborrow that we can safely ignore, because
                             // the next adjustment can only be a Deref
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index a6f904b0c96..0294dab17d5 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -445,11 +445,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             // Fix up the autoderefs. Autorefs can only occur immediately preceding
             // overloaded lvalue ops, and will be fixed by them in order to get
             // the correct region.
-            let mut source = self.node_ty(expr.id);
+            let mut source = self.node_ty(expr.hir_id);
             // Do not mutate adjustments in place, but rather take them,
             // and replace them after mutating them, to avoid having the
             // tables borrowed during (`deref_mut`) method resolution.
-            let previous_adjustments = self.tables.borrow_mut().adjustments.remove(&expr.id);
+            let previous_adjustments = self.tables
+                                           .borrow_mut()
+                                           .adjustments
+                                           .remove(&expr.hir_id.local_id);
             if let Some(mut adjustments) = previous_adjustments {
                 let pref = LvaluePreference::PreferMutLvalue;
                 for adjustment in &mut adjustments {
@@ -466,12 +469,12 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                     }
                     source = adjustment.target;
                 }
-                self.tables.borrow_mut().adjustments.insert(expr.id, adjustments);
+                self.tables.borrow_mut().adjustments.insert(expr.hir_id.local_id, adjustments);
             }
 
             match expr.node {
                 hir::ExprIndex(ref base_expr, ref index_expr) => {
-                    let index_expr_ty = self.node_ty(index_expr.id);
+                    let index_expr_ty = self.node_ty(index_expr.hir_id);
                     self.convert_lvalue_op_to_mutable(
                         LvalueOp::Index, expr, base_expr, &[index_expr_ty]);
                 }
@@ -498,7 +501,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         }
 
         let base_ty = self.tables.borrow().expr_adjustments(base_expr).last()
-            .map_or_else(|| self.node_ty(expr.id), |adj| adj.target);
+            .map_or_else(|| self.node_ty(expr.hir_id), |adj| adj.target);
         let base_ty = self.resolve_type_vars_if_possible(&base_ty);
 
         // Need to deref because overloaded lvalue ops take self by-reference.
@@ -513,7 +516,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             None => return self.tcx.sess.delay_span_bug(expr.span, "re-trying op failed")
         };
         debug!("convert_lvalue_op_to_mutable: method={:?}", method);
-        self.write_method_call((expr.id, expr.hir_id), method);
+        self.write_method_call(expr.hir_id, method);
 
         let (region, mutbl) = if let ty::TyRef(r, mt) = method.sig.inputs()[0].sty {
             (r, mt.mutbl)
@@ -523,8 +526,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         // Convert the autoref in the base expr to mutable with the correct
         // region and mutability.
-        let base_expr_ty = self.node_ty(base_expr.id);
-        if let Some(adjustments) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
+        let base_expr_ty = self.node_ty(base_expr.hir_id);
+        if let Some(adjustments) = self.tables
+                                       .borrow_mut()
+                                       .adjustments
+                                       .get_mut(&base_expr.hir_id.local_id) {
             let mut source = base_expr_ty;
             for adjustment in &mut adjustments[..] {
                 if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 885472a76a9..facacdc8d11 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1024,7 +1024,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
             fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation);
         }
 
-        fcx.write_ty(arg.id, arg_ty);
+        fcx.write_ty(arg.hir_id, arg_ty);
     }
 
     inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
@@ -1807,10 +1807,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     #[inline]
-    pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
-        debug!("write_ty({}, {:?}) in fcx {}",
-               node_id, self.resolve_type_vars_if_possible(&ty), self.tag());
-        self.tables.borrow_mut().node_types.insert(node_id, ty);
+    pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) {
+        debug!("write_ty({:?}, {:?}) in fcx {}",
+               id, self.resolve_type_vars_if_possible(&ty), self.tag());
+        {
+            let mut tables = self.tables.borrow_mut();
+            tables.validate_hir_id(id);
+            tables.node_types.insert(id.local_id, ty);
+        }
 
         if ty.references_error() {
             self.has_errors.set(true);
@@ -1821,24 +1825,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // The NodeId and the ItemLocalId must identify the same item. We just pass
     // both of them for consistency checking.
     pub fn write_method_call(&self,
-                             (node_id, hir_id): (ast::NodeId, hir::HirId),
+                             hir_id: hir::HirId,
                              method: MethodCallee<'tcx>) {
         {
             let mut tables = self.tables.borrow_mut();
             tables.validate_hir_id(hir_id);
             tables.type_dependent_defs.insert(hir_id.local_id, Def::Method(method.def_id));
         }
-        self.write_substs(node_id, method.substs);
+        self.write_substs(hir_id, method.substs);
     }
 
-    pub fn write_substs(&self, node_id: ast::NodeId, substs: &'tcx Substs<'tcx>) {
+    pub fn write_substs(&self, node_id: hir::HirId, substs: &'tcx Substs<'tcx>) {
         if !substs.is_noop() {
-            debug!("write_substs({}, {:?}) in fcx {}",
+            debug!("write_substs({:?}, {:?}) in fcx {}",
                    node_id,
                    substs,
                    self.tag());
 
-            self.tables.borrow_mut().node_substs.insert(node_id, substs);
+            let mut tables = self.tables.borrow_mut();
+            tables.validate_hir_id(node_id);
+            tables.node_substs.insert(node_id.local_id, substs);
         }
     }
 
@@ -1849,7 +1855,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             return;
         }
 
-        match self.tables.borrow_mut().adjustments.entry(expr.id) {
+        let mut tables = self.tables.borrow_mut();
+        tables.validate_hir_id(expr.hir_id);
+        match tables.adjustments.entry(expr.hir_id.local_id) {
             Entry::Vacant(entry) => { entry.insert(adj); },
             Entry::Occupied(mut entry) => {
                 debug!(" - composing on top of {:?}", entry.get());
@@ -2002,13 +2010,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         t
     }
 
-    pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
-        match self.tables.borrow().node_types.get(&id) {
+    pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
+        let tables = self.tables.borrow();
+        tables.validate_hir_id(id);
+        match tables.node_types.get(&id.local_id) {
             Some(&t) => t,
             None if self.err_count_since_creation() != 0 => self.tcx.types.err,
             None => {
+                let node_id = self.tcx.hir.definitions().find_node_for_hir_id(id);
                 bug!("no type for node {}: {} in fcx {}",
-                     id, self.tcx.hir.node_to_string(id),
+                     node_id, self.tcx.hir.node_to_string(node_id),
                      self.tag());
             }
         }
@@ -2276,7 +2287,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
                 self.apply_adjustments(base_expr, adjustments);
 
-                self.write_method_call((expr.id, expr.hir_id), method);
+                self.write_method_call(expr.hir_id, method);
                 (input_ty, self.make_overloaded_lvalue_return_type(method).ty)
             });
             if result.is_some() {
@@ -2665,7 +2676,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // While we don't allow *arbitrary* coercions here, we *do* allow
         // coercions from ! to `expected`.
         if ty.is_never() {
-            assert!(!self.tables.borrow().adjustments.contains_key(&expr.id),
+            assert!(!self.tables.borrow().adjustments.contains_key(&expr.hir_id.local_id),
                     "expression with never type wound up being adjusted");
             let adj_ty = self.next_diverging_ty_var(
                 TypeVariableOrigin::AdjustmentType(expr.span));
@@ -2816,7 +2827,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                               expr,
                                               rcvr) {
             Ok(method) => {
-                self.write_method_call((expr.id, expr.hir_id), method);
+                self.write_method_call(expr.hir_id, method);
                 Ok(method)
             }
             Err(error) => {
@@ -3448,7 +3459,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Record the type, which applies it effects.
         // We need to do this after the warning above, so that
         // we don't warn for the diverging expression itself.
-        self.write_ty(expr.id, ty);
+        self.write_ty(expr.hir_id, ty);
 
         // Combine the diverging and has_error flags.
         self.diverges.set(self.diverges.get() | old_diverges);
@@ -3521,7 +3532,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 }]);
                             }
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
-                            self.write_method_call((expr.id, expr.hir_id), method);
+                            self.write_method_call(expr.hir_id, method);
                         } else {
                             type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614,
                                                "type `{}` cannot be dereferenced",
@@ -3599,7 +3610,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
               // We always require that the type provided as the value for
               // a type parameter outlives the moment of instantiation.
-              let substs = self.tables.borrow().node_substs(expr.id);
+              let substs = self.tables.borrow().node_substs(expr.hir_id);
               self.add_wf_bounds(substs, expr);
 
               ty
@@ -4101,19 +4112,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     pub fn check_decl_local(&self, local: &'gcx hir::Local)  {
         let t = self.local_ty(local.span, local.id);
-        self.write_ty(local.id, t);
+        self.write_ty(local.hir_id, t);
 
         if let Some(ref init) = local.init {
             let init_ty = self.check_decl_initializer(local, &init);
             if init_ty.references_error() {
-                self.write_ty(local.id, init_ty);
+                self.write_ty(local.hir_id, init_ty);
             }
         }
 
         self.check_pat(&local.pat, t);
-        let pat_ty = self.node_ty(local.pat.id);
+        let pat_ty = self.node_ty(local.pat.hir_id);
         if pat_ty.references_error() {
-            self.write_ty(local.id, pat_ty);
+            self.write_ty(local.hir_id, pat_ty);
         }
     }
 
@@ -4265,7 +4276,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             ty = self.tcx.types.err
         }
 
-        self.write_ty(blk.id, ty);
+        self.write_ty(blk.hir_id, ty);
 
         *self.ps.borrow_mut() = prev;
         ty
@@ -4443,7 +4454,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir::StmtSemi(ref e, _) => e,
             _ => return,
         };
-        let last_expr_ty = self.node_ty(last_expr.id);
+        let last_expr_ty = self.node_ty(last_expr.hir_id);
         if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
             return;
         }
@@ -4586,7 +4597,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let nid = self.tcx.hir.as_local_node_id(def_id).unwrap();
                 let ty = self.local_ty(span, nid);
                 let ty = self.normalize_associated_types_in(span, &ty);
-                self.write_ty(node_id, ty);
+                self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty);
                 return ty;
             }
             _ => {}
@@ -4718,7 +4729,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         debug!("instantiate_value_path: type of {:?} is {:?}",
                node_id,
                ty_substituted);
-        self.write_substs(node_id, substs);
+        self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs);
         ty_substituted
     }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 71457377b10..f2104b8dbae 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -210,11 +210,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // some cases applied on the RHS, on top of which we need
                         // to autoref, which is not allowed by apply_adjustments.
                         // self.apply_adjustments(rhs_expr, vec![autoref]);
-                        self.tables.borrow_mut().adjustments.entry(rhs_expr.id)
+                        let mut tables = self.tables.borrow_mut();
+                        tables.validate_hir_id(rhs_expr.hir_id);
+                        tables.adjustments.entry(rhs_expr.hir_id.local_id)
                             .or_insert(vec![]).push(autoref);
                     }
                 }
-                self.write_method_call((expr.id, expr.hir_id), method);
+                self.write_method_call(expr.hir_id, method);
 
                 method.sig.output()
             }
@@ -340,7 +342,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         assert!(op.is_by_value());
         match self.lookup_op_method(operand_ty, &[], Op::Unary(op, ex.span)) {
             Ok(method) => {
-                self.write_method_call((ex.id, ex.hir_id), method);
+                self.write_method_call(ex.hir_id, method);
                 method.sig.output()
             }
             Err(()) => {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 9b7ecc194ca..d88ed888338 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Try to resolve the type for the given node.
-    fn resolve_node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
+    fn resolve_node_type(&self, id: hir::HirId) -> Ty<'tcx> {
         let t = self.node_ty(id);
         self.resolve_type(t)
     }
@@ -338,8 +338,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
         debug!("visit_fn_body body.id {:?} call_site_scope: {:?}",
                body.id(), call_site_scope);
         let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
+        let body_hir_id = self.tcx.hir.node_to_hir_id(body_id.node_id);
         self.type_of_node_must_outlive(infer::CallReturn(span),
-                                       body_id.node_id,
+                                       body_hir_id,
                                        call_site_region);
 
         self.region_bound_pairs.truncate(old_region_bounds_pairs_len);
@@ -613,9 +614,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
             let var_region = self.tcx.mk_region(ty::ReScope(var_scope));
 
             let origin = infer::BindingTypeIsNotValidAtDecl(span);
-            self.type_of_node_must_outlive(origin, id, var_region);
+            let hir_id = self.tcx.hir.node_to_hir_id(id);
+            self.type_of_node_must_outlive(origin, hir_id, var_region);
 
-            let typ = self.resolve_node_type(id);
+            let typ = self.resolve_node_type(hir_id);
             let _ = dropck::check_safety_of_destructor_if_necessary(
                 self, typ, span, var_scope);
         })
@@ -664,7 +666,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
 
         // No matter what, the type of each expression must outlive the
         // scope of that expression. This also guarantees basic WF.
-        let expr_ty = self.resolve_node_type(expr.id);
+        let expr_ty = self.resolve_node_type(expr.hir_id);
         // the region corresponding to this expression
         let expr_region = self.tcx.node_scope_region(expr.id);
         self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span),
@@ -686,7 +688,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                     infer::ParameterOrigin::OverloadedOperator
             };
 
-            let substs = self.tables.borrow().node_substs(expr.id);
+            let substs = self.tables.borrow().node_substs(expr.hir_id);
             self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
             // Arguments (sub-expressions) are checked via `constrain_call`, below.
         }
@@ -709,7 +711,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                expr, self.repeating_scope);
         match expr.node {
             hir::ExprPath(_) => {
-                let substs = self.tables.borrow().node_substs(expr.id);
+                let substs = self.tables.borrow().node_substs(expr.hir_id);
                 let origin = infer::ParameterOrigin::Path;
                 self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
             }
@@ -718,7 +720,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                 if is_method_call {
                     self.constrain_call(expr, Some(&callee), args.iter().map(|e| &*e));
                 } else {
-                    self.constrain_callee(callee.id, expr, &callee);
+                    self.constrain_callee(&callee);
                     self.constrain_call(expr, None, args.iter().map(|e| &*e));
                 }
 
@@ -812,7 +814,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                 // adjustments*.
                 //
                 // FIXME(#6268) nested method calls requires that this rule change
-                let ty0 = self.resolve_node_type(expr.id);
+                let ty0 = self.resolve_node_type(expr.hir_id);
                 self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region);
                 intravisit::walk_expr(self, expr);
             }
@@ -849,7 +851,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                        ret_expr.id, call_site_scope);
                 let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope.unwrap()));
                 self.type_of_node_must_outlive(infer::CallReturn(ret_expr.span),
-                                               ret_expr.id,
+                                               ret_expr.hir_id,
                                                call_site_region);
                 intravisit::walk_expr(self, expr);
             }
@@ -870,8 +872,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                cast_expr,
                source_expr);
 
-        let source_ty = self.resolve_node_type(source_expr.id);
-        let target_ty = self.resolve_node_type(cast_expr.id);
+        let source_ty = self.resolve_node_type(source_expr.hir_id);
+        let target_ty = self.resolve_node_type(cast_expr.hir_id);
 
         self.walk_cast(cast_expr, source_ty, target_ty);
     }
@@ -915,11 +917,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
         self.set_repeating_scope(repeating_scope);
     }
 
-    fn constrain_callee(&mut self,
-                        callee_id: ast::NodeId,
-                        _call_expr: &hir::Expr,
-                        _callee_expr: &hir::Expr) {
-        let callee_ty = self.resolve_node_type(callee_id);
+    fn constrain_callee(&mut self, callee_expr: &hir::Expr) {
+        let callee_ty = self.resolve_node_type(callee_expr.hir_id);
         match callee_ty.sty {
             ty::TyFnDef(..) | ty::TyFnPtr(_) => { }
             _ => {
@@ -962,14 +961,16 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
             // ensure that any regions appearing in the argument type are
             // valid for at least the lifetime of the function:
             self.type_of_node_must_outlive(infer::CallArg(arg_expr.span),
-                                           arg_expr.id, callee_region);
+                                           arg_expr.hir_id,
+                                           callee_region);
         }
 
         // as loop above, but for receiver
         if let Some(r) = receiver {
             debug!("receiver: {:?}", r);
             self.type_of_node_must_outlive(infer::CallRcvr(r.span),
-                                           r.id, callee_region);
+                                           r.hir_id,
+                                           callee_region);
         }
     }
 
@@ -1038,7 +1039,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                 //
                 // FIXME(#6268) remove to support nested method calls
                 self.type_of_node_must_outlive(infer::AutoBorrow(expr.span),
-                                               expr.id, expr_region);
+                                               expr.hir_id,
+                                               expr_region);
             }
 
             cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
@@ -1109,21 +1111,27 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     /// adjustments) are valid for at least `minimum_lifetime`
     fn type_of_node_must_outlive(&mut self,
         origin: infer::SubregionOrigin<'tcx>,
-        id: ast::NodeId,
+        hir_id: hir::HirId,
         minimum_lifetime: ty::Region<'tcx>)
     {
         // Try to resolve the type.  If we encounter an error, then typeck
         // is going to fail anyway, so just stop here and let typeck
         // report errors later on in the writeback phase.
-        let ty0 = self.resolve_node_type(id);
-        let ty = self.tables.borrow().adjustments.get(&id)
-            .and_then(|adj| adj.last())
-            .map_or(ty0, |adj| adj.target);
+        let ty0 = self.resolve_node_type(hir_id);
+
+        let ty = {
+            let tables = self.tables.borrow();
+            tables.validate_hir_id(hir_id);
+            tables.adjustments
+                  .get(&hir_id.local_id)
+                  .and_then(|adj| adj.last())
+                  .map_or(ty0, |adj| adj.target)
+        };
         let ty = self.resolve_type(ty);
         debug!("constrain_regions_in_type_of_node(\
-                ty={}, ty0={}, id={}, minimum_lifetime={:?})",
+                ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
                 ty,  ty0,
-               id, minimum_lifetime);
+                hir_id, minimum_lifetime);
         self.type_must_outlive(origin, ty, minimum_lifetime);
     }
 
@@ -1137,7 +1145,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 
         debug!("link_addr_of: cmt={:?}", cmt);
 
-        self.link_region_from_node_type(expr.span, expr.id, mutability, cmt);
+        self.link_region_from_node_type(expr.span, expr.hir_id, mutability, cmt);
     }
 
     /// Computes the guarantors for any ref bindings in a `let` and
@@ -1173,7 +1181,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
         debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
         for arg in args {
-            let arg_ty = self.node_ty(arg.id);
+            let arg_ty = self.node_ty(arg.hir_id);
             let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
             let arg_cmt = self.with_mc(|mc| {
                 mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty)
@@ -1200,7 +1208,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                         let bm = *mc.tables.pat_binding_modes.get(&sub_pat.id)
                                                              .expect("missing binding mode");
                         if let ty::BindByReference(mutbl) = bm {
-                            self.link_region_from_node_type(sub_pat.span, sub_pat.id,
+                            self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id,
                                                             mutbl, sub_cmt);
                         }
                     }
@@ -1236,7 +1244,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     /// which must be some reference (`&T`, `&str`, etc).
     fn link_region_from_node_type(&self,
                                   span: Span,
-                                  id: ast::NodeId,
+                                  id: hir::HirId,
                                   mutbl: hir::Mutability,
                                   cmt_borrowed: mc::cmt<'tcx>) {
         debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 59ca896b347..22047ed583e 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
             hir::ExprClosure(cc, _, body_id, _) => {
                 let body = self.fcx.tcx.hir.body(body_id);
                 self.visit_body(body);
-                self.fcx.analyze_closure(expr.id, expr.span, body, cc);
+                self.fcx.analyze_closure((expr.id, expr.hir_id), expr.span, body, cc);
             }
 
             _ => { }
@@ -90,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn analyze_closure(&self,
-                       id: ast::NodeId,
+                       (id, hir_id): (ast::NodeId, hir::HirId),
                        span: Span,
                        body: &hir::Body,
                        capture_clause: hir::CaptureClause) {
@@ -172,7 +172,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // inference algorithm will reject it).
 
         // Extract the type variables UV0...UVn.
-        let (def_id, closure_substs) = match self.node_ty(id).sty {
+        let (def_id, closure_substs) = match self.node_ty(hir_id).sty {
             ty::TyClosure(def_id, substs) => (def_id, substs),
             ref t => {
                 span_bug!(
@@ -216,7 +216,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             freevars.iter().map(|freevar| {
                 let def_id = freevar.def.def_id();
                 let var_id = tcx.hir.as_local_node_id(def_id).unwrap();
-                let freevar_ty = self.node_ty(var_id);
+                let freevar_ty = self.node_ty(tcx.hir.node_to_hir_id(var_id));
                 let upvar_id = ty::UpvarId {
                     var_id: var_id,
                     closure_expr_id: closure_id
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 93d0e6e976a..058cef71d4a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -35,7 +35,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let mut wbcx = WritebackCx::new(self, body);
         for arg in &body.arguments {
-            wbcx.visit_node_id(arg.pat.span, (arg.id, arg.hir_id));
+            wbcx.visit_node_id(arg.pat.span, arg.hir_id);
         }
         wbcx.visit_body(body);
         wbcx.visit_upvar_borrow_map();
@@ -90,10 +90,11 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         self.fcx.tcx
     }
 
-    fn write_ty_to_tables(&mut self, node_id: ast::NodeId, ty: Ty<'gcx>) {
-        debug!("write_ty_to_tables({}, {:?})", node_id,  ty);
+    fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
+        debug!("write_ty_to_tables({:?}, {:?})", hir_id,  ty);
         assert!(!ty.needs_infer());
-        self.tables.node_types.insert(node_id, ty);
+        self.tables.validate_hir_id(hir_id);
+        self.tables.node_types.insert(hir_id.local_id, ty);
     }
 
     // Hacky hack: During type-checking, we treat *all* operators
@@ -104,39 +105,39 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         match e.node {
             hir::ExprUnary(hir::UnNeg, ref inner) |
             hir::ExprUnary(hir::UnNot, ref inner)  => {
-                let inner_ty = self.fcx.node_ty(inner.id);
+                let inner_ty = self.fcx.node_ty(inner.hir_id);
                 let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
 
                 if inner_ty.is_scalar() {
                     let mut tables = self.fcx.tables.borrow_mut();
                     tables.validate_hir_id(e.hir_id);
                     tables.type_dependent_defs.remove(&e.hir_id.local_id);
-                    tables.node_substs.remove(&e.id);
+                    tables.node_substs.remove(&e.hir_id.local_id);
                 }
             }
             hir::ExprBinary(ref op, ref lhs, ref rhs) |
             hir::ExprAssignOp(ref op, ref lhs, ref rhs) => {
-                let lhs_ty = self.fcx.node_ty(lhs.id);
+                let lhs_ty = self.fcx.node_ty(lhs.hir_id);
                 let lhs_ty = self.fcx.resolve_type_vars_if_possible(&lhs_ty);
 
-                let rhs_ty = self.fcx.node_ty(rhs.id);
+                let rhs_ty = self.fcx.node_ty(rhs.hir_id);
                 let rhs_ty = self.fcx.resolve_type_vars_if_possible(&rhs_ty);
 
                 if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
                     let mut tables = self.fcx.tables.borrow_mut();
                     tables.validate_hir_id(e.hir_id);
                     tables.type_dependent_defs.remove(&e.hir_id.local_id);
-                    tables.node_substs.remove(&e.id);
+                    tables.node_substs.remove(&e.hir_id.local_id);
 
                     match e.node {
                         hir::ExprBinary(..) => {
                             if !op.node.is_by_value() {
-                                tables.adjustments.get_mut(&lhs.id).map(|a| a.pop());
-                                tables.adjustments.get_mut(&rhs.id).map(|a| a.pop());
+                                tables.adjustments.get_mut(&lhs.hir_id.local_id).map(|a| a.pop());
+                                tables.adjustments.get_mut(&rhs.hir_id.local_id).map(|a| a.pop());
                             }
                         },
                         hir::ExprAssignOp(..) => {
-                            tables.adjustments.get_mut(&lhs.id).map(|a| a.pop());
+                            tables.adjustments.get_mut(&lhs.hir_id.local_id).map(|a| a.pop());
                         },
                         _ => {},
                     }
@@ -163,12 +164,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     fn visit_expr(&mut self, e: &'gcx hir::Expr) {
         self.fix_scalar_builtin_expr(e);
 
-        self.visit_node_id(e.span, (e.id, e.hir_id));
+        self.visit_node_id(e.span, e.hir_id);
 
         if let hir::ExprClosure(_, _, body, _) = e.node {
             let body = self.fcx.tcx.hir.body(body);
             for arg in &body.arguments {
-                self.visit_node_id(e.span, (arg.id, arg.hir_id));
+                self.visit_node_id(e.span, arg.hir_id);
             }
 
             self.visit_body(body);
@@ -178,7 +179,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     }
 
     fn visit_block(&mut self, b: &'gcx hir::Block) {
-        self.visit_node_id(b.span, (b.id, b.hir_id));
+        self.visit_node_id(b.span, b.hir_id);
         intravisit::walk_block(self, b);
     }
 
@@ -192,7 +193,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
             _ => {}
         };
 
-        self.visit_node_id(p.span, (p.id, p.hir_id));
+        self.visit_node_id(p.span, p.hir_id);
         intravisit::walk_pat(self, p);
     }
 
@@ -200,7 +201,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
         intravisit::walk_local(self, l);
         let var_ty = self.fcx.local_ty(l.span, l.id);
         let var_ty = self.resolve(&var_ty, &l.span);
-        self.write_ty_to_tables(l.id, var_ty);
+        self.write_ty_to_tables(l.hir_id, var_ty);
     }
 }
 
@@ -279,13 +280,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 }
             });
 
-            self.tables.node_types.insert(node_id, outside_ty);
+            let hir_id = self.tcx().hir.node_to_hir_id(node_id);
+            self.tables.validate_hir_id(hir_id);
+            self.tables.node_types.insert(hir_id.local_id, outside_ty);
         }
     }
 
-    fn visit_node_id(&mut self,
-                     span: Span,
-                     (node_id, hir_id): (ast::NodeId, hir::HirId)) {
+    fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
         {
             let mut fcx_tables = self.fcx.tables.borrow_mut();
             fcx_tables.validate_hir_id(hir_id);
@@ -297,34 +298,39 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         }
 
         // Resolve any borrowings for the node with id `node_id`
-        self.visit_adjustments(span, node_id);
+        self.visit_adjustments(span, hir_id);
 
         // Resolve the type of the node with id `node_id`
-        let n_ty = self.fcx.node_ty(node_id);
+        let n_ty = self.fcx.node_ty(hir_id);
         let n_ty = self.resolve(&n_ty, &span);
-        self.write_ty_to_tables(node_id, n_ty);
-        debug!("Node {} has type {:?}", node_id, n_ty);
+        self.write_ty_to_tables(hir_id, n_ty);
+        debug!("Node {:?} has type {:?}", hir_id, n_ty);
 
         // Resolve any substitutions
-        if let Some(&substs) = self.fcx.tables.borrow().node_substs.get(&node_id) {
+        if let Some(&substs) = self.fcx.tables.borrow().node_substs.get(&hir_id.local_id) {
             let substs = self.resolve(&substs, &span);
-            debug!("write_substs_to_tcx({}, {:?})", node_id, substs);
+            debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
             assert!(!substs.needs_infer());
-            self.tables.node_substs.insert(node_id, substs);
+            self.tables.node_substs.insert(hir_id.local_id, substs);
         }
     }
 
-    fn visit_adjustments(&mut self, span: Span, node_id: ast::NodeId) {
-        let adjustment = self.fcx.tables.borrow_mut().adjustments.remove(&node_id);
+    fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) {
+        let adjustment = {
+            let mut fcx_tables = self.fcx.tables.borrow_mut();
+            fcx_tables.validate_hir_id(hir_id);
+            fcx_tables.adjustments.remove(&hir_id.local_id)
+        };
         match adjustment {
             None => {
-                debug!("No adjustments for node {}", node_id);
+                debug!("No adjustments for node {:?}", hir_id);
             }
 
             Some(adjustment) => {
                 let resolved_adjustment = self.resolve(&adjustment, &span);
-                debug!("Adjustments for node {}: {:?}", node_id, resolved_adjustment);
-                self.tables.adjustments.insert(node_id, resolved_adjustment);
+                debug!("Adjustments for node {:?}: {:?}", hir_id, resolved_adjustment);
+                self.tables.validate_hir_id(hir_id);
+                self.tables.adjustments.insert(hir_id.local_id, resolved_adjustment);
             }
         }
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fba32dbb889..7b63bd883f9 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1187,7 +1187,8 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         NodeTy(&hir::Ty { node: TyImplTrait(..), .. }) => {
             let owner = tcx.hir.get_parent_did(node_id);
-            tcx.typeck_tables_of(owner).node_id_to_type(node_id)
+            let hir_id = tcx.hir.node_to_hir_id(node_id);
+            tcx.typeck_tables_of(owner).node_id_to_type(hir_id)
         }
 
         x => {