From 3b99a48c4dbca21e7baa3f7747c58209359474c7 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Wed, 3 Apr 2019 09:07:45 +0200
Subject: [PATCH 1/2] HirIdify hir::Def

---
 src/librustc/hir/def.rs                       |  79 +++++++--
 src/librustc/hir/lowering.rs                  | 154 ++++++++++++++----
 src/librustc/hir/map/mod.rs                   |   5 +-
 src/librustc/hir/mod.rs                       |  17 +-
 src/librustc/middle/expr_use_visitor.rs       |   6 +-
 src/librustc/middle/liveness.rs               |   9 +-
 src/librustc/middle/mem_categorization.rs     |   8 +-
 src/librustc/middle/reachable.rs              |   3 +-
 src/librustc/mir/mod.rs                       |   4 +-
 src/librustc/query/mod.rs                     |   4 +-
 src/librustc/ty/context.rs                    |  12 +-
 src/librustc/ty/mod.rs                        |   2 +-
 src/librustc/ty/print/pretty.rs               |   4 +-
 src/librustc_metadata/cstore_impl.rs          |   9 +-
 src/librustc_metadata/decoder.rs              |   2 +-
 src/librustc_metadata/schema.rs               |   2 +-
 .../borrow_check/error_reporting.rs           |   2 +-
 src/librustc_mir/hair/cx/expr.rs              |   9 +-
 src/librustc_resolve/build_reduced_graph.rs   |  18 +-
 src/librustc_resolve/error_reporting.rs       |   6 +-
 src/librustc_resolve/lib.rs                   |  17 +-
 src/librustc_resolve/macros.rs                |   4 +-
 src/librustc_resolve/resolve_imports.rs       |   4 +-
 src/librustc_save_analysis/dump_visitor.rs    |   4 +-
 src/librustc_save_analysis/lib.rs             |   4 +-
 src/librustc_typeck/check/callee.rs           |   4 +-
 src/librustc_typeck/check/demand.rs           |   4 +-
 src/librustc_typeck/check/method/suggest.rs   |   8 +-
 src/librustc_typeck/check/mod.rs              |   3 +-
 src/librustc_typeck/check/upvar.rs            |   7 +-
 .../passes/collect_intra_doc_links.rs         |   4 +-
 31 files changed, 300 insertions(+), 118 deletions(-)

diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 3cc23ccdb642c..7d173af311264 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -2,10 +2,12 @@ use crate::hir::def_id::DefId;
 use crate::util::nodemap::{NodeMap, DefIdMap};
 use syntax::ast;
 use syntax::ext::base::MacroKind;
+use syntax::ast::NodeId;
 use syntax_pos::Span;
 use rustc_macros::HashStable;
 use crate::hir;
 use crate::ty;
+use std::fmt::Debug;
 
 use self::Namespace::*;
 
@@ -43,7 +45,7 @@ pub enum NonMacroAttrKind {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
-pub enum Def {
+pub enum Def<Id = hir::HirId> {
     // Type namespace
     Mod(DefId),
     /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
@@ -78,8 +80,8 @@ pub enum Def {
     Method(DefId),
     AssociatedConst(DefId),
 
-    Local(ast::NodeId),
-    Upvar(ast::NodeId,  // `NodeId` of closed over local
+    Local(Id),
+    Upvar(Id,           // `HirId` of closed over local
           usize,        // index in the `freevars` list of the closure
           ast::NodeId), // expr node that creates the closure
     Label(ast::NodeId),
@@ -108,22 +110,22 @@ pub enum Def {
 /// ```
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
-    base_def: Def,
+    base_def: Def<NodeId>,
     unresolved_segments: usize,
 }
 
 impl PathResolution {
-    pub fn new(def: Def) -> Self {
+    pub fn new(def: Def<NodeId>) -> Self {
         PathResolution { base_def: def, unresolved_segments: 0 }
     }
 
-    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
+    pub fn with_unresolved_segments(def: Def<NodeId>, mut unresolved_segments: usize) -> Self {
         if def == Def::Err { unresolved_segments = 0 }
         PathResolution { base_def: def, unresolved_segments: unresolved_segments }
     }
 
     #[inline]
-    pub fn base_def(&self) -> Def {
+    pub fn base_def(&self) -> Def<NodeId> {
         self.base_def
     }
 
@@ -215,18 +217,18 @@ pub type DefMap = NodeMap<PathResolution>;
 
 /// This is the replacement export map. It maps a module to all of the exports
 /// within.
-pub type ExportMap = DefIdMap<Vec<Export>>;
+pub type ExportMap<Id> = DefIdMap<Vec<Export<Id>>>;
 
 /// Map used to track the `use` statements within a scope, matching it with all the items in every
 /// namespace.
 pub type ImportMap = NodeMap<PerNS<Option<PathResolution>>>;
 
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Export {
+pub struct Export<Id> {
     /// The name of the target.
     pub ident: ast::Ident,
     /// The definition of the target.
-    pub def: Def,
+    pub def: Def<Id>,
     /// The span of the target definition.
     pub span: Span,
     /// The visibility of the export.
@@ -234,6 +236,17 @@ pub struct Export {
     pub vis: ty::Visibility,
 }
 
+impl<Id> Export<Id> {
+    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
+        Export {
+            ident: self.ident,
+            def: self.def.map_id(map),
+            span: self.span,
+            vis: self.vis,
+        }
+    }
+}
+
 impl CtorKind {
     pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
         match *vdata {
@@ -264,9 +277,12 @@ impl NonMacroAttrKind {
     }
 }
 
-impl Def {
+impl<Id> Def<Id> {
     /// Return the `DefId` of this `Def` if it has an id, else panic.
-    pub fn def_id(&self) -> DefId {
+    pub fn def_id(&self) -> DefId
+    where
+        Id: Debug,
+    {
         self.opt_def_id().unwrap_or_else(|| {
             bug!("attempted .def_id() on invalid def: {:?}", self)
         })
@@ -358,4 +374,43 @@ impl Def {
             _ => "a",
         }
     }
+
+    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Def<R> {
+        match self {
+            Def::Fn(id) => Def::Fn(id),
+            Def::Mod(id) => Def::Mod(id),
+            Def::Static(id, is_mutbl) => Def::Static(id, is_mutbl),
+            Def::Enum(id) => Def::Enum(id),
+            Def::Variant(id) => Def::Variant(id),
+            Def::Ctor(a, b, c) => Def::Ctor(a, b, c),
+            Def::Struct(id) => Def::Struct(id),
+            Def::Existential(id) => Def::Existential(id),
+            Def::TyAlias(id) => Def::TyAlias(id),
+            Def::TraitAlias(id) => Def::TraitAlias(id),
+            Def::AssociatedTy(id) => Def::AssociatedTy(id),
+            Def::AssociatedExistential(id) => Def::AssociatedExistential(id),
+            Def::SelfCtor(id) => Def::SelfCtor(id),
+            Def::Union(id) => Def::Union(id),
+            Def::Trait(id) => Def::Trait(id),
+            Def::ForeignTy(id) => Def::ForeignTy(id),
+            Def::Method(id) => Def::Method(id),
+            Def::Const(id) => Def::Const(id),
+            Def::AssociatedConst(id) => Def::AssociatedConst(id),
+            Def::TyParam(id) => Def::TyParam(id),
+            Def::ConstParam(id) => Def::ConstParam(id),
+            Def::PrimTy(id) => Def::PrimTy(id),
+            Def::Local(id) => Def::Local(map(id)),
+            Def::Upvar(id, index, closure) => Def::Upvar(
+                map(id),
+                index,
+                closure
+            ),
+            Def::Label(id) => Def::Label(id),
+            Def::SelfTy(a, b) => Def::SelfTy(a, b),
+            Def::Macro(id, macro_kind) => Def::Macro(id, macro_kind),
+            Def::ToolMod => Def::ToolMod,
+            Def::NonMacroAttr(attr_kind) => Def::NonMacroAttr(attr_kind),
+            Def::Err => Def::Err,
+        }
+    }
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 2a25552367678..a8269bb139570 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -401,6 +401,7 @@ impl<'a> LoweringContext<'a> {
         /// declared for every type and trait definition.
         struct MiscCollector<'lcx, 'interner: 'lcx> {
             lctx: &'lcx mut LoweringContext<'interner>,
+            hir_id_owner: Option<NodeId>,
         }
 
         impl MiscCollector<'_, '_> {
@@ -432,9 +433,34 @@ impl<'a> LoweringContext<'a> {
                     }
                 }
             }
+
+            fn with_hir_id_owner<F, T>(&mut self, owner: Option<NodeId>, f: F) -> T
+            where
+                F: FnOnce(&mut Self) -> T,
+            {
+                let old = mem::replace(&mut self.hir_id_owner, owner);
+                let r = f(self);
+                self.hir_id_owner = old;
+                r
+            }
         }
 
         impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
+            fn visit_pat(&mut self, p: &'lcx Pat) {
+                match p.node {
+                    // Doesn't generate a Hir node
+                    PatKind::Paren(..) => {},
+                    _ => {
+
+                        if let Some(owner) = self.hir_id_owner {
+                            self.lctx.lower_node_id_with_owner(p.id, owner);
+                        }
+                    }
+                };
+
+                visit::walk_pat(self, p)
+            }
+
             fn visit_item(&mut self, item: &'lcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id).hir_id;
 
@@ -461,17 +487,63 @@ impl<'a> LoweringContext<'a> {
                     }
                     _ => {}
                 }
-                visit::walk_item(self, item);
+
+                self.with_hir_id_owner(Some(item.id), |this| {
+                    visit::walk_item(this, item);
+                });
             }
 
             fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_trait_item(self, item);
+
+                match item.node {
+                    TraitItemKind::Method(_, None) => {
+                        // Ignore patterns in trait methods without bodies
+                        self.with_hir_id_owner(None, |this| {
+                            visit::walk_trait_item(this, item)
+                        });
+                    }
+                    _ => self.with_hir_id_owner(Some(item.id), |this| {
+                        visit::walk_trait_item(this, item);
+                    })
+                }
             }
 
             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_impl_item(self, item);
+                self.with_hir_id_owner(Some(item.id), |this| {
+                    visit::walk_impl_item(this, item);
+                });
+            }
+
+            fn visit_foreign_item(&mut self, i: &'lcx ForeignItem) {
+                // Ignore patterns in foreign items
+                self.with_hir_id_owner(None, |this| {
+                    visit::walk_foreign_item(this, i)
+                });
+            }
+
+            fn visit_ty(&mut self, t: &'lcx Ty) {
+                match t.node {
+                    // Mirrors the case in visit::walk_ty
+                    TyKind::BareFn(ref f) => {
+                        walk_list!(
+                            self,
+                            visit_generic_param,
+                            &f.generic_params
+                        );
+                        // Mirrors visit::walk_fn_decl
+                        for argument in &f.decl.inputs {
+                            // We don't lower the ids of argument patterns
+                            self.with_hir_id_owner(None, |this| {
+                                this.visit_pat(&argument.pat);
+                            });
+                            self.visit_ty(&argument.ty)
+                        }
+                        self.visit_fn_ret_ty(&f.decl.output)
+                    }
+                    _ => visit::walk_ty(self, t),
+                }
             }
         }
 
@@ -565,7 +637,7 @@ impl<'a> LoweringContext<'a> {
         self.lower_node_id(CRATE_NODE_ID);
         debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == hir::CRATE_HIR_ID);
 
-        visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
+        visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c);
         visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
 
         let module = self.lower_mod(&c.module);
@@ -729,7 +801,15 @@ impl<'a> LoweringContext<'a> {
         self.lower_node_id(self.sess.next_node_id())
     }
 
-    fn expect_full_def(&mut self, id: NodeId) -> Def {
+    fn lower_def(&mut self, def: Def<NodeId>) -> Def {
+        def.map_id(|id| {
+            self.lower_node_id_generic(id, |_| {
+                panic!("expected node_id to be lowered already for def {:#?}", def)
+            }).hir_id
+        })
+    }
+
+    fn expect_full_def(&mut self, id: NodeId) -> Def<NodeId> {
         self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
             if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
@@ -738,7 +818,7 @@ impl<'a> LoweringContext<'a> {
         })
     }
 
-    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def> {
+    fn expect_full_def_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Def<NodeId>> {
         self.resolver.get_import(id).present_items().map(|pr| {
             if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
@@ -1324,14 +1404,20 @@ impl<'a> LoweringContext<'a> {
                 }
                 return ty;
             }
-            TyKind::ImplicitSelf => hir::TyKind::Path(hir::QPath::Resolved(
-                None,
-                P(hir::Path {
-                    def: self.expect_full_def(t.id),
-                    segments: hir_vec![hir::PathSegment::from_ident(keywords::SelfUpper.ident())],
-                    span: t.span,
-                }),
-            )),
+            TyKind::ImplicitSelf => {
+                let def = self.expect_full_def(t.id);
+                let def = self.lower_def(def);
+                hir::TyKind::Path(hir::QPath::Resolved(
+                    None,
+                    P(hir::Path {
+                        def,
+                        segments: hir_vec![hir::PathSegment::from_ident(
+                            keywords::SelfUpper.ident()
+                        )],
+                        span: t.span,
+                    }),
+                ))
+            },
             TyKind::Array(ref ty, ref length) => {
                 hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length))
             }
@@ -1755,7 +1841,7 @@ impl<'a> LoweringContext<'a> {
 
         let proj_start = p.segments.len() - resolution.unresolved_segments();
         let path = P(hir::Path {
-            def: resolution.base_def(),
+            def: self.lower_def(resolution.base_def()),
             segments: p.segments[..proj_start]
                 .iter()
                 .enumerate()
@@ -1931,6 +2017,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path {
         let def = self.expect_full_def(id);
+        let def = self.lower_def(def);
         self.lower_path_extra(def, p, param_mode, None)
     }
 
@@ -2042,7 +2129,7 @@ impl<'a> LoweringContext<'a> {
         hir::PathSegment::new(
             segment.ident,
             Some(id.hir_id),
-            Some(def),
+            Some(self.lower_def(def)),
             generic_args,
             infer_types,
         )
@@ -3174,7 +3261,7 @@ impl<'a> LoweringContext<'a> {
                 let mut defs = self.expect_full_def_from_use(id);
                 // We want to return *something* from this function, so hold onto the first item
                 // for later.
-                let ret_def = defs.next().unwrap_or(Def::Err);
+                let ret_def = self.lower_def(defs.next().unwrap_or(Def::Err));
 
                 // Here, we are looping over namespaces, if they exist for the definition
                 // being imported. We only handle type and value namespaces because we
@@ -3192,6 +3279,7 @@ impl<'a> LoweringContext<'a> {
 
                     self.with_hir_id_owner(new_node_id, |this| {
                         let new_id = this.lower_node_id(new_node_id);
+                        let def = this.lower_def(def);
                         let path =
                             this.lower_path_extra(def, &path, ParamMode::Explicit, None);
                         let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
@@ -3347,6 +3435,7 @@ impl<'a> LoweringContext<'a> {
                 }
 
                 let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err);
+                let def = self.lower_def(def);
                 let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None));
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
@@ -3780,7 +3869,7 @@ impl<'a> LoweringContext<'a> {
                         None,
                         P(hir::Path {
                             span: ident.span,
-                            def,
+                            def: self.lower_def(def),
                             segments: hir_vec![hir::PathSegment::from_ident(ident)],
                         }),
                     )),
@@ -4435,7 +4524,7 @@ impl<'a> LoweringContext<'a> {
                 let iter = self.str_to_ident("iter");
 
                 let next_ident = self.str_to_ident("__next");
-                let (next_pat, next_pat_nid) = self.pat_ident_binding_mode(
+                let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
                     desugared_span,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
@@ -4444,9 +4533,9 @@ impl<'a> LoweringContext<'a> {
                 // `::std::option::Option::Some(val) => next = val`
                 let pat_arm = {
                     let val_ident = self.str_to_ident("val");
-                    let (val_pat, val_pat_nid) = self.pat_ident(pat.span, val_ident);
-                    let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_nid));
-                    let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_nid));
+                    let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
+                    let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
+                    let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
                     let assign = P(self.expr(
                         pat.span,
                         hir::ExprKind::Assign(next_expr, val_expr),
@@ -4497,7 +4586,7 @@ impl<'a> LoweringContext<'a> {
                     span: head_sp,
                 };
 
-                let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_nid));
+                let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));
 
                 // `let mut __next`
                 let next_let = self.stmt_let_pat(
@@ -4790,6 +4879,7 @@ impl<'a> LoweringContext<'a> {
                     self.lower_node_id(id)
                 };
                 let def = self.expect_full_def(id);
+                let def = self.lower_def(def);
                 hir::VisibilityKind::Restricted {
                     path: P(self.lower_path_extra(
                         def,
@@ -4891,7 +4981,7 @@ impl<'a> LoweringContext<'a> {
         self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
     }
 
-    fn expr_ident(&mut self, span: Span, ident: Ident, binding: NodeId) -> hir::Expr {
+    fn expr_ident(&mut self, span: Span, ident: Ident, binding: hir::HirId) -> hir::Expr {
         self.expr_ident_with_attrs(span, ident, binding, ThinVec::new())
     }
 
@@ -4899,7 +4989,7 @@ impl<'a> LoweringContext<'a> {
         &mut self,
         span: Span,
         ident: Ident,
-        binding: NodeId,
+        binding: hir::HirId,
         attrs: ThinVec<Attribute>,
     ) -> hir::Expr {
         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
@@ -4994,8 +5084,8 @@ impl<'a> LoweringContext<'a> {
         mutbl: bool,
         ident: Ident,
         ex: P<hir::Expr>,
-    ) -> (hir::Stmt, NodeId) {
-        let (pat, pat_nid) = if mutbl {
+    ) -> (hir::Stmt, hir::HirId) {
+        let (pat, pat_hid) = if mutbl {
             self.pat_ident_binding_mode(sp, ident, hir::BindingAnnotation::Mutable)
         } else {
             self.pat_ident(sp, ident)
@@ -5003,7 +5093,7 @@ impl<'a> LoweringContext<'a> {
 
         (
             self.stmt_let_pat(sp, Some(ex), pat, hir::LocalSource::Normal),
-            pat_nid,
+            pat_hid,
         )
     }
 
@@ -5061,7 +5151,7 @@ impl<'a> LoweringContext<'a> {
         self.pat(span, pt)
     }
 
-    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, NodeId) {
+    fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, hir::HirId) {
         self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
     }
 
@@ -5070,8 +5160,8 @@ impl<'a> LoweringContext<'a> {
         span: Span,
         ident: Ident,
         bm: hir::BindingAnnotation,
-    ) -> (P<hir::Pat>, NodeId) {
-        let LoweredNodeId { node_id, hir_id } = self.next_id();
+    ) -> (P<hir::Pat>, hir::HirId) {
+        let LoweredNodeId { node_id: _, hir_id } = self.next_id();
 
         (
             P(hir::Pat {
@@ -5079,7 +5169,7 @@ impl<'a> LoweringContext<'a> {
                 node: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
                 span,
             }),
-            node_id
+            hir_id
         )
     }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index c0579ef0f7a96..4eef2019e26fb 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -393,7 +393,7 @@ impl<'hir> Map<'hir> {
             Node::Block(_) |
             Node::Crate => None,
             Node::Local(local) => {
-                Some(Def::Local(self.hir_to_node_id(local.hir_id)))
+                Some(Def::Local(local.hir_id))
             }
             Node::MacroDef(macro_def) => {
                 Some(Def::Macro(self.local_def_id_from_hir_id(macro_def.hir_id),
@@ -402,8 +402,7 @@ impl<'hir> Map<'hir> {
             Node::GenericParam(param) => {
                 Some(match param.kind {
                     GenericParamKind::Lifetime { .. } => {
-                        let node_id = self.hir_to_node_id(param.hir_id);
-                        Def::Local(node_id)
+                        Def::Local(param.hir_id)
                     },
                     GenericParamKind::Type { .. } => Def::TyParam(
                         self.local_def_id_from_hir_id(param.hir_id)),
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 58a27d3f78eec..7ed8c08c92337 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -2424,16 +2424,23 @@ impl ForeignItemKind {
 
 /// A free variable referred to in a function.
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Freevar {
+pub struct Freevar<Id = HirId> {
     /// The variable being accessed free.
-    pub def: Def,
+    pub def: def::Def<Id>,
 
     // First span where it is accessed (there can be multiple).
     pub span: Span
 }
 
-impl Freevar {
-    pub fn var_id(&self) -> NodeId {
+impl<Id: fmt::Debug + Copy> Freevar<Id> {
+    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Freevar<R> {
+        Freevar {
+            def: self.def.map_id(map),
+            span: self.span,
+        }
+    }
+
+    pub fn var_id(&self) -> Id {
         match self.def {
             Def::Local(id) | Def::Upvar(id, ..) => id,
             _ => bug!("Freevar::var_id: bad def ({:?})", self.def)
@@ -2441,7 +2448,7 @@ impl Freevar {
     }
 }
 
-pub type FreevarMap = NodeMap<Vec<Freevar>>;
+pub type FreevarMap = NodeMap<Vec<Freevar<ast::NodeId>>>;
 
 pub type CaptureModeMap = NodeMap<CaptureClause>;
 
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 4f630fe9a3911..41ff9406d9df2 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -863,7 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
 
                     // Each match binding is effectively an assignment to the
                     // binding being produced.
-                    let def = Def::Local(mc.tcx.hir().hir_to_node_id(canonical_id));
+                    let def = Def::Local(canonical_id);
                     if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) {
                         delegate.mutate(pat.hir_id, pat.span, binding_cmt, MutateMode::Init);
                     }
@@ -930,7 +930,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id);
         self.tcx().with_freevars(closure_expr.hir_id, |freevars| {
             for freevar in freevars {
-                let var_hir_id = self.tcx().hir().node_to_hir_id(freevar.var_id());
+                let var_hir_id = freevar.var_id();
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath { hir_id: var_hir_id },
                     closure_expr_id: closure_def_id.to_local(),
@@ -967,7 +967,7 @@ 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_hir_id = self.tcx().hir().node_to_hir_id(upvar.var_id());
+        let var_hir_id = upvar.var_id();
         let var_ty = self.mc.node_ty(var_hir_id)?;
         self.mc.cat_def(closure_hir_id, closure_span, var_ty, upvar.def)
     }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index f5a95d7004bff..d167b44d42f89 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -487,8 +487,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
             call_caps.extend(freevars.iter().filter_map(|fv| {
                 if let Def::Local(rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
-                    let var_hid = ir.tcx.hir().node_to_hir_id(rv);
-                    Some(CaptureInfo { ln: fv_ln, var_hid })
+                    Some(CaptureInfo { ln: fv_ln, var_hid: rv })
                 } else {
                     None
                 }
@@ -1347,7 +1346,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn access_path(&mut self, hir_id: HirId, path: &hir::Path, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match path.def {
-            Def::Local(nid) => {
+            Def::Local(hid) => {
+              let nid = self.ir.tcx.hir().hir_to_node_id(hid);
               self.access_var(hir_id, nid, succ, acc, path.span)
             }
             _ => succ
@@ -1539,13 +1539,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn check_place(&mut self, expr: &'tcx Expr) {
         match expr.node {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
-                if let Def::Local(nid) = path.def {
+                if let Def::Local(var_hid) = path.def {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
                     // as being used.
                     let ln = self.live_node(expr.hir_id, expr.span);
-                    let var_hid = self.ir.tcx.hir().node_to_hir_id(nid);
                     let var = self.variable(var_hid, expr.span);
                     self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
                 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 1a3fef18404e3..a031037b7a070 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -734,15 +734,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
 
             Def::Upvar(var_id, _, fn_node_id) => {
-                self.cat_upvar(hir_id, span, var_id, fn_node_id)
+                let var_nid = self.tcx.hir().hir_to_node_id(var_id);
+                self.cat_upvar(hir_id, span, var_nid, fn_node_id)
             }
 
             Def::Local(vid) => {
+                let vnid = self.tcx.hir().hir_to_node_id(vid);
                 Ok(cmt_ {
                     hir_id,
                     span,
-                    cat: Categorization::Local(self.tcx.hir().node_to_hir_id(vid)),
-                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
+                    cat: Categorization::Local(vid),
+                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vnid),
                     ty: expr_ty,
                     note: NoteNone
                 })
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index b55e840596b85..92266838dd820 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -103,8 +103,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
         };
 
         match def {
-            Some(Def::Local(node_id)) | Some(Def::Upvar(node_id, ..)) => {
-                let hir_id = self.tcx.hir().node_to_hir_id(node_id);
+            Some(Def::Local(hir_id)) | Some(Def::Upvar(hir_id, ..)) => {
                 self.reachable_symbols.insert(hir_id);
             }
             Some(def) => {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 8424c096e88c0..65501e316efc4 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2455,7 +2455,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 
                             tcx.with_freevars(hir_id, |freevars| {
                                 for (freevar, place) in freevars.iter().zip(places) {
-                                    let var_name = tcx.hir().name(freevar.var_id());
+                                    let var_name = tcx.hir().name_by_hir_id(freevar.var_id());
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                             });
@@ -2474,7 +2474,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 
                             tcx.with_freevars(hir_id, |freevars| {
                                 for (freevar, place) in freevars.iter().zip(places) {
-                                    let var_name = tcx.hir().name(freevar.var_id());
+                                    let var_name = tcx.hir().name_by_hir_id(freevar.var_id());
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                                 struct_fmt.field("$state", &places[freevars.len()]);
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index d0ad2c90668a5..bc9aaf870ceed 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -641,7 +641,7 @@ rustc_queries! {
     }
 
     Other {
-        query module_exports(_: DefId) -> Option<Lrc<Vec<Export>>> {
+        query module_exports(_: DefId) -> Option<Lrc<Vec<Export<hir::HirId>>>> {
             eval_always
         }
     }
@@ -781,7 +781,7 @@ rustc_queries! {
             eval_always
             desc { "fetching what a crate is named" }
         }
-        query item_children(_: DefId) -> Lrc<Vec<Export>> {}
+        query item_children(_: DefId) -> Lrc<Vec<Export<hir::HirId>>> {}
         query extern_mod_stmt_cnum(_: DefId) -> Option<CrateNum> {}
 
         query get_lib_features(_: CrateNum) -> Lrc<LibFeatures> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7dc4dee3fbf91..9bd5b2fdb9619 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1024,7 +1024,7 @@ pub struct GlobalCtxt<'tcx> {
                                        Lrc<StableVec<TraitCandidate>>>>>,
 
     /// Export map produced by name resolution.
-    export_map: FxHashMap<DefId, Lrc<Vec<Export>>>,
+    export_map: FxHashMap<DefId, Lrc<Vec<Export<hir::HirId>>>>,
 
     hir_map: hir_map::Map<'tcx>,
 
@@ -1271,10 +1271,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             types: common_types,
             trait_map,
             export_map: resolutions.export_map.into_iter().map(|(k, v)| {
-                (k, Lrc::new(v))
+                let exports: Vec<_> = v.into_iter().map(|e| {
+                    e.map_id(|id| hir.node_to_hir_id(id))
+                }).collect();
+                (k, Lrc::new(exports))
             }).collect(),
             freevars: resolutions.freevars.into_iter().map(|(k, v)| {
-                (hir.local_def_id(k), Lrc::new(v))
+                let vars: Vec<_> = v.into_iter().map(|e| {
+                    e.map_id(|id| hir.node_to_hir_id(id))
+                }).collect();
+                (hir.local_def_id(k), Lrc::new(vars))
             }).collect(),
             maybe_unused_trait_imports:
                 resolutions.maybe_unused_trait_imports
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7d47867cea125..d24395ac9c182 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -123,7 +123,7 @@ pub struct Resolutions {
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
-    pub export_map: ExportMap,
+    pub export_map: ExportMap<NodeId>,
     pub glob_map: GlobMap,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index c9a4961a8e044..b31ba10d523a5 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -592,7 +592,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name(freevar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(freevar.var_id())),
                             print(upvar_ty));
                         sep = ", ";
                     }
@@ -635,7 +635,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name(freevar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(freevar.var_id())),
                             print(upvar_ty));
                         sep = ", ";
                     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 995532a00cd6e..e3bf09299ef00 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -11,6 +11,7 @@ use rustc::middle::cstore::{CrateStore, DepKind,
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
 use rustc::hir::def;
+use rustc::hir;
 use rustc::session::{CrateDisambiguator, Session};
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::query::Providers;
@@ -347,7 +348,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
             {
                 let visible_parent_map = &mut visible_parent_map;
                 let mut add_child = |bfs_queue: &mut VecDeque<_>,
-                                     child: &def::Export,
+                                     child: &def::Export<hir::HirId>,
                                      parent: DefId| {
                     if child.vis != ty::Visibility::Public {
                         return;
@@ -415,7 +416,11 @@ impl cstore::CStore {
         self.get_crate_data(def.krate).get_item_attrs(def.index, sess)
     }
 
-    pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
+    pub fn item_children_untracked(
+        &self,
+        def_id: DefId,
+        sess: &Session
+    ) -> Vec<def::Export<hir::HirId>> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate)
             .each_child_of_item(def_id.index, |child| result.push(child), sess);
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index f456a5c1619c5..f7ea67ef34948 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -734,7 +734,7 @@ impl<'a, 'tcx> CrateMetadata {
 
     /// Iterates over each child of the given item.
     pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
-        where F: FnMut(def::Export)
+        where F: FnMut(def::Export<hir::HirId>)
     {
         if let Some(ref proc_macros) = self.proc_macros {
             /* If we are loading as a proc macro, we want to return the view of this crate
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index fe2ea26c32741..504c7da7d6b9e 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -423,7 +423,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
-    pub reexports: LazySeq<def::Export>,
+    pub reexports: LazySeq<def::Export<hir::HirId>>,
 }
 
 impl_stable_hash_for!(struct ModData { reexports });
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index e6d818152f58e..3ab0996d3a17f 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1824,7 +1824,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         .tcx
                         .with_freevars(hir_id, |fv| fv[field.index()]);
 
-                    self.infcx.tcx.hir().name(freevar.var_id()).to_string()
+                    self.infcx.tcx.hir().name_by_hir_id(freevar.var_id()).to_string()
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 91113dc2271be..2c22c5e64c4f0 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -986,14 +986,13 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
     match def {
-        Def::Local(id) => ExprKind::VarRef { id: cx.tcx.hir().node_to_hir_id(id) },
+        Def::Local(id) => ExprKind::VarRef { id },
 
-        Def::Upvar(var_id, index, closure_expr_id) => {
+        Def::Upvar(var_hir_id, index, closure_expr_id) => {
             debug!("convert_var(upvar({:?}, {:?}, {:?}))",
-                   var_id,
+                   var_hir_id,
                    index,
                    closure_expr_id);
-            let var_hir_id = cx.tcx.hir().node_to_hir_id(var_id);
             let var_ty = cx.tables().node_type(var_hir_id);
 
             // FIXME free regions in closures are not right
@@ -1195,7 +1194,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    freevar: &hir::Freevar,
                                    freevar_ty: Ty<'tcx>)
                                    -> ExprRef<'tcx> {
-    let var_hir_id = cx.tcx.hir().node_to_hir_id(freevar.var_id());
+    let var_hir_id = freevar.var_id();
     let upvar_id = ty::UpvarId {
         var_path: ty::UpvarPath { hir_id: var_hir_id },
         closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 7ce264db755db..72dd043f21435 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -12,7 +12,7 @@ use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
 use crate::{resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::bug;
-use rustc::hir::def::*;
+use rustc::hir::def::{self, *};
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
@@ -44,6 +44,8 @@ use syntax_pos::{Span, DUMMY_SP};
 
 use log::debug;
 
+type Def = def::Def<NodeId>;
+
 impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
     fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
         arenas.alloc_name_binding(NameBinding {
@@ -641,7 +643,11 @@ impl<'a> Resolver<'a> {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
+    fn build_reduced_graph_for_external_crate_def(
+        &mut self,
+        parent: Module<'a>,
+        child: Export<ast::NodeId>,
+    ) {
         let Export { ident, def, vis, span } = child;
         // FIXME: We shouldn't create the gensym here, it should come from metadata,
         // but metadata cannot encode gensyms currently, so we create it here.
@@ -684,13 +690,14 @@ impl<'a> Resolver<'a> {
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
 
                 for child in self.cstore.item_children_untracked(def_id, self.session) {
-                    let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
+                    let def = child.def.map_id(|_| panic!("unexpected id"));
+                    let ns = if let Def::AssociatedTy(..) = def { TypeNS } else { ValueNS };
                     self.define(module, child.ident, ns,
-                                (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
+                                (def, ty::Visibility::Public, DUMMY_SP, expansion));
 
                     if self.cstore.associated_item_cloned_untracked(child.def.def_id())
                            .method_has_self_argument {
-                        self.has_self.insert(child.def.def_id());
+                        self.has_self.insert(def.def_id());
                     }
                 }
                 module.populated.set(true);
@@ -777,6 +784,7 @@ impl<'a> Resolver<'a> {
         if module.populated.get() { return }
         let def_id = module.def_id().unwrap();
         for child in self.cstore.item_children_untracked(def_id, self.session) {
+            let child = child.map_id(|_| panic!("unexpected id"));
             self.build_reduced_graph_for_external_crate_def(module, child);
         }
         module.populated.set(true)
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 931bce91d7d43..9e3894dab0da0 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -2,14 +2,16 @@ use std::cmp::Reverse;
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
-use rustc::hir::def::{Def, CtorKind, Namespace::*};
+use rustc::hir::def::{self, CtorKind, Namespace::*};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::session::{Session, config::nightly_options};
-use syntax::ast::{Expr, ExprKind, Ident};
+use syntax::ast::{self, Expr, ExprKind, Ident};
 use syntax::ext::base::MacroKind;
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{BytePos, Span};
 
+type Def = def::Def<ast::NodeId>;
+
 use crate::macros::ParentScope;
 use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string};
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b34786d8f129a..96aac97729797 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4,6 +4,7 @@
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(type_alias_enum_variants)]
 
 #![recursion_limit="256"]
 
@@ -20,7 +21,9 @@ use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::lint;
-use rustc::hir::def::*;
+use rustc::hir::def::{
+    self, PathResolution, CtorKind, CtorOf, NonMacroAttrKind, DefMap, ImportMap, ExportMap
+};
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
@@ -66,6 +69,8 @@ use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_pr
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
 use macros::{InvocationData, LegacyBinding, ParentScope};
 
+type Def = def::Def<NodeId>;
+
 // N.B., this module needs to be declared first so diagnostics are
 // registered before they are used.
 mod diagnostics;
@@ -1563,7 +1568,7 @@ pub struct Resolver<'a> {
     import_map: ImportMap,
     pub freevars: FreevarMap,
     freevars_seen: NodeMap<NodeMap<usize>>,
-    pub export_map: ExportMap,
+    pub export_map: ExportMap<NodeId>,
     pub trait_map: TraitMap,
 
     /// A map from nodes to anonymous modules.
@@ -1773,7 +1778,7 @@ impl<'a> Resolver<'a> {
             }
         };
         let path = self.resolve_hir_path_cb(&path, is_value, |_, _, _| errored = true);
-        if errored || path.def == Def::Err {
+        if errored || path.def == def::Def::Err {
             Err(())
         } else {
             Ok(path)
@@ -1819,12 +1824,14 @@ impl<'a> Resolver<'a> {
 
         let segments: Vec<_> = segments.iter().map(|seg| {
             let mut hir_seg = hir::PathSegment::from_ident(seg.ident);
-            hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def()));
+            hir_seg.def = Some(self.def_map.get(&seg.id).map_or(def::Def::Err, |p| {
+                p.base_def().map_id(|_| panic!("unexpected node_id"))
+            }));
             hir_seg
         }).collect();
         hir::Path {
             span,
-            def,
+            def: def.map_id(|_| panic!("unexpected node_id")),
             segments: segments.into(),
         }
     }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 21ca8ea369fd9..64f652d6eebaa 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,7 @@ use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
                          CrateNum, DefIndexAddressSpace};
-use rustc::hir::def::{Def, NonMacroAttrKind};
+use rustc::hir::def::{self, NonMacroAttrKind};
 use rustc::hir::map::{self, DefCollector};
 use rustc::{ty, lint};
 use rustc::{bug, span_bug};
@@ -33,6 +33,8 @@ use std::cell::Cell;
 use std::{mem, ptr};
 use rustc_data_structures::sync::Lrc;
 
+type Def = def::Def<ast::NodeId>;
+
 #[derive(Clone, Debug)]
 pub struct InvocationData<'a> {
     def_index: DefIndex,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 62af6e19603c4..9f6395fa9071a 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -21,7 +21,7 @@ use rustc::lint::builtin::{
     UNUSED_IMPORTS,
 };
 use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::def::*;
+use rustc::hir::def::{self, PathResolution, Export};
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
@@ -39,6 +39,8 @@ use log::*;
 use std::cell::{Cell, RefCell};
 use std::{mem, ptr};
 
+type Def = def::Def<NodeId>;
+
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
 pub enum ImportDirectiveSubclass<'a> {
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 7d4002525942b..a5ddf89d3d439 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -915,13 +915,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         // process collected paths
         for (id, ident, immut) in collector.collected_idents {
             match self.save_ctxt.get_path_def(id) {
-                HirDef::Local(id) => {
+                HirDef::Local(hir_id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
                         self.span.snippet(ident.span)
                     } else {
                         "<mutable>".to_owned()
                     };
-                    let hir_id = self.tcx.hir().node_to_hir_id(id);
+                    let id = self.tcx.hir().hir_to_node_id(hir_id);
                     let typ = self.save_ctxt
                         .tables
                         .node_type_opt(hir_id)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index d6923b4490d59..ce0decaee496f 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -659,7 +659,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Node::Binding(&hir::Pat {
                 node: hir::PatKind::Binding(_, canonical_id, ..),
                 ..
-            }) => HirDef::Local(self.tcx.hir().hir_to_node_id(canonical_id)),
+            }) => HirDef::Local(canonical_id),
 
             _ => HirDef::Err,
         }
@@ -707,7 +707,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
-                    ref_id: id_from_node_id(id, self),
+                    ref_id: id_from_node_id(self.tcx.hir().hir_to_node_id(id), self),
                 })
             }
             HirDef::Trait(def_id) if fn_type(path_seg) => {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 15ae39600f6b4..b8c0baff69b28 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -350,7 +350,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                     let def_span = match def {
                         Def::Err => None,
-                        Def::Local(id) | Def::Upvar(id, ..) => Some(self.tcx.hir().span(id)),
+                        Def::Local(id) | Def::Upvar(id, ..) => {
+                            Some(self.tcx.hir().span_by_hir_id(id))
+                        },
                         _ => def
                             .opt_def_id()
                             .and_then(|did| self.tcx.hir().span_if_local(did)),
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 8739147c621e6..8c1f4aabb1b2b 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -236,12 +236,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     ) -> Option<(Span, &'static str, String)> {
         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
             if let hir::def::Def::Local(id) = path.def {
-                let parent = self.tcx.hir().get_parent_node(id);
+                let parent = self.tcx.hir().get_parent_node_by_hir_id(id);
                 if let Some(Node::Expr(hir::Expr {
                     hir_id,
                     node: hir::ExprKind::Closure(_, decl, ..),
                     ..
-                })) = self.tcx.hir().find(parent) {
+                })) = self.tcx.hir().find_by_hir_id(parent) {
                     let parent = self.tcx.hir().get_parent_node_by_hir_id(*hir_id);
                     if let (Some(Node::Expr(hir::Expr {
                         node: hir::ExprKind::MethodCall(path, span, expr),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 31b7724d63816..ff889c89770af 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -249,14 +249,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             ExprKind::Path(ref qpath) => {
                                 // local binding
                                 if let &QPath::Resolved(_, ref path) = &qpath {
-                                    if let hir::def::Def::Local(node_id) = path.def {
-                                        let span = tcx.hir().span(node_id);
+                                    if let hir::def::Def::Local(hir_id) = path.def {
+                                        let span = tcx.hir().span_by_hir_id(hir_id);
                                         let snippet = tcx.sess.source_map().span_to_snippet(span)
                                             .unwrap();
                                         let filename = tcx.sess.source_map().span_to_filename(span);
 
-                                        let parent_node = self.tcx.hir().get(
-                                            self.tcx.hir().get_parent_node(node_id),
+                                        let parent_node = self.tcx.hir().get_by_hir_id(
+                                            self.tcx.hir().get_parent_node_by_hir_id(hir_id),
                                         );
                                         let msg = format!(
                                             "you must specify a type for this binding, like `{}`",
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 313ed19b945d1..0f076aaa20509 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -5397,8 +5397,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let tcx = self.tcx;
 
         match def {
-            Def::Local(nid) | Def::Upvar(nid, ..) => {
-                let hid = self.tcx.hir().node_to_hir_id(nid);
+            Def::Local(hid) | Def::Upvar(hid, ..) => {
                 let ty = self.local_ty(span, hid).decl_ty;
                 let ty = self.normalize_associated_types_in(span, &ty);
                 self.write_ty(hir_id, ty);
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index a76dfdd69ba97..dc66c6c93d0e0 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             for freevar in freevars {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath {
-                        hir_id: self.tcx.hir().node_to_hir_id(freevar.var_id()),
+                        hir_id: freevar.var_id(),
                     },
                     closure_expr_id: LocalDefId::from_def_id(closure_def_id),
                 };
@@ -250,8 +250,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             freevars
                 .iter()
                 .map(|freevar| {
-                    let var_node_id = freevar.var_id();
-                    let var_hir_id = tcx.hir().node_to_hir_id(var_node_id);
+                    let var_hir_id = freevar.var_id();
                     let freevar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
                         var_path: ty::UpvarPath { hir_id: var_hir_id },
@@ -261,7 +260,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                     debug!(
                         "var_id={:?} freevar_ty={:?} capture={:?}",
-                        var_node_id, freevar_ty, capture
+                        var_hir_id, freevar_ty, capture
                     );
 
                     match capture {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index dbc55b62ef848..a62b33686485f 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -429,12 +429,12 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Def> {
                 // skip proc-macro stubs, they'll cause `get_macro` to crash
             } else {
                 if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) {
-                    return Some(def);
+                    return Some(def.map_id(|_| panic!("unexpected id")));
                 }
             }
         }
         if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
-            return Some(*def);
+            return Some(def.map_id(|_| panic!("unexpected id")));
         }
         None
     })

From b5d43fcdc9512e538c6d2070df0ad2fed35f85bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Thu, 11 Apr 2019 18:33:36 +0200
Subject: [PATCH 2/2] Update tests

---
 src/test/mir-opt/inline-closure-borrows-arg.rs | 2 +-
 src/test/mir-opt/inline-closure.rs             | 2 +-
 src/test/mir-opt/retag.rs                      | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs
index d09ddce09c547..2c30c7f365148 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline-closure-borrows-arg.rs
@@ -20,7 +20,7 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
 // ...
 // bb0: {
 //     ...
-//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 27 }];
+//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 29 }];
 //     ...
 //     _4 = &_3;
 //     ...
diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs
index 436a8c20e2b49..8116a445467ff 100644
--- a/src/test/mir-opt/inline-closure.rs
+++ b/src/test/mir-opt/inline-closure.rs
@@ -16,7 +16,7 @@ fn foo<T: Copy>(_t: T, q: i32) -> i32 {
 // ...
 // bb0: {
 //     ...
-//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 11 }];
+//     _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 13 }];
 //     ...
 //     _4 = &_3;
 //     ...
diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs
index 3b333b5431c3e..1f8abf10fa549 100644
--- a/src/test/mir-opt/retag.rs
+++ b/src/test/mir-opt/retag.rs
@@ -98,7 +98,7 @@ fn main() {
 // }
 // END rustc.main.EraseRegions.after.mir
 // START rustc.main-{{closure}}.EraseRegions.after.mir
-// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 70 }], _2: &i32) -> &i32 {
+// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 72 }], _2: &i32) -> &i32 {
 //     ...
 //     bb0: {
 //         Retag([fn entry] _1);