about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-06-04 14:16:13 +0000
committerbors <bors@rust-lang.org>2020-06-04 14:16:13 +0000
commit3d5d0f898c2f3998e50c2180c6202f193c3acdbc (patch)
treea2607b6c46b42115e7e12d3f6f481bb335e14fed
parent2a5cbb0e42f330617a061243f8725d861dd5118b (diff)
parent70228f97abaeac7549702503bad10bdb89de00c1 (diff)
downloadrust-3d5d0f898c2f3998e50c2180c6202f193c3acdbc.tar.gz
rust-3d5d0f898c2f3998e50c2180c6202f193c3acdbc.zip
Auto merge of #72882 - marmeladema:save-analysis-hir-tree, r=Xanewok
save_analysis: work on HIR tree instead of AST

In order to reduce the uses of `NodeId`s in the compiler, `save_analysis` crate has been reworked to operate on the HIR tree instead of the AST.

cc #50928
-rw-r--r--src/librustc_driver/lib.rs16
-rw-r--r--src/librustc_hir_pretty/lib.rs24
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs916
-rw-r--r--src/librustc_save_analysis/lib.rs473
-rw-r--r--src/librustc_save_analysis/sig.rs471
m---------src/tools/rls0
6 files changed, 902 insertions, 998 deletions
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 68ce93d3db9..ccea041699e 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -346,12 +346,15 @@ pub fn run_compiler(
 
             queries.global_ctxt()?;
 
+            // Drop AST after creating GlobalCtxt to free memory
+            let _timer = sess.prof.generic_activity("drop_ast");
+            mem::drop(queries.expansion()?.take());
+
             if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json {
                 return early_exit();
             }
 
             if sess.opts.debugging_opts.save_analysis {
-                let expanded_crate = &queries.expansion()?.peek().0;
                 let crate_name = queries.crate_name()?.peek().clone();
                 queries.global_ctxt()?.peek_mut().enter(|tcx| {
                     let result = tcx.analysis(LOCAL_CRATE);
@@ -359,7 +362,6 @@ pub fn run_compiler(
                     sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
-                            &expanded_crate,
                             &crate_name,
                             &compiler.input(),
                             None,
@@ -371,13 +373,7 @@ pub fn run_compiler(
                     });
 
                     result
-                    // AST will be dropped *after* the `after_analysis` callback
-                    // (needed by the RLS)
                 })?;
-            } else {
-                // Drop AST after creating GlobalCtxt to free memory
-                let _timer = sess.prof.generic_activity("drop_ast");
-                mem::drop(queries.expansion()?.take());
             }
 
             queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
@@ -386,10 +382,6 @@ pub fn run_compiler(
                 return early_exit();
             }
 
-            if sess.opts.debugging_opts.save_analysis {
-                mem::drop(queries.expansion()?.take());
-            }
-
             queries.ongoing_codegen()?;
 
             if sess.opts.debugging_opts.print_type_sizes {
diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs
index 8eb19cbb65a..e642915b86a 100644
--- a/src/librustc_hir_pretty/lib.rs
+++ b/src/librustc_hir_pretty/lib.rs
@@ -203,6 +203,30 @@ pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_
     })
 }
 
+pub fn generic_params_to_string(generic_params: &[GenericParam<'_>]) -> String {
+    to_string(NO_ANN, |s| s.print_generic_params(generic_params))
+}
+
+pub fn bounds_to_string<'b>(bounds: impl IntoIterator<Item = &'b hir::GenericBound<'b>>) -> String {
+    to_string(NO_ANN, |s| s.print_bounds("", bounds))
+}
+
+pub fn param_to_string(arg: &hir::Param<'_>) -> String {
+    to_string(NO_ANN, |s| s.print_param(arg))
+}
+
+pub fn ty_to_string(ty: &hir::Ty<'_>) -> String {
+    to_string(NO_ANN, |s| s.print_type(ty))
+}
+
+pub fn path_segment_to_string(segment: &hir::PathSegment<'_>) -> String {
+    to_string(NO_ANN, |s| s.print_path_segment(segment))
+}
+
+pub fn path_to_string(segment: &hir::Path<'_>) -> String {
+    to_string(NO_ANN, |s| s.print_path(segment, false))
+}
+
 impl<'a> State<'a> {
     pub fn cbox(&mut self, u: usize) {
         self.s.cbox(u);
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 3dd715f9e3d..a5e61ab9ab0 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -13,19 +13,19 @@
 //! DumpVisitor walks the AST and processes it, and Dumper is used for
 //! recording the output.
 
-use rustc_ast::ast::{self, Attribute, NodeId, PatKind};
-use rustc_ast::ptr::P;
-use rustc_ast::token;
-use rustc_ast::visit::{self, Visitor};
-use rustc_ast::walk_list;
-use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to_string};
+use rustc_ast::ast::{self};
+use rustc_ast::{token, walk_list};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir_pretty::{bounds_to_string, generic_params_to_string, ty_to_string};
+use rustc_middle::hir::map::Map;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::config::Input;
-use rustc_span::source_map::{respan, DUMMY_SP};
+use rustc_span::source_map::respan;
 use rustc_span::symbol::Ident;
 use rustc_span::*;
 
@@ -36,7 +36,7 @@ use crate::dumper::{Access, Dumper};
 use crate::sig;
 use crate::span_utils::SpanUtils;
 use crate::{
-    escape, generated_code, id_from_def_id, id_from_node_id, lower_attributes, PathCollector,
+    escape, generated_code, id_from_def_id, id_from_hir_id, lower_attributes, PathCollector,
     SaveContext,
 };
 
@@ -124,11 +124,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.save_ctxt.span_from_span(span)
     }
 
-    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
+    fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
         self.save_ctxt.lookup_def_id(ref_id)
     }
 
-    pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
+    pub fn dump_crate_info(&mut self, name: &str, krate: &hir::Crate<'_>) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
             let source_file = Path::new(source_file);
@@ -151,7 +151,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
-            span: self.span_from_span(krate.span),
+            span: self.span_from_span(krate.item.span),
         };
 
         self.dumper.crate_prelude(data);
@@ -199,8 +199,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.dumper.compilation_opts(data);
     }
 
-    fn write_sub_paths(&mut self, path: &ast::Path) {
-        for seg in &path.segments {
+    fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
+        for seg in path.segments {
             if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
                 self.dumper.dump_ref(data);
             }
@@ -209,7 +209,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
     // As write_sub_paths, but does not process the last ident in the path (assuming it
     // will be processed elsewhere). See note on write_sub_paths about global.
-    fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
+    fn write_sub_paths_truncated(&mut self, path: &'tcx hir::Path<'tcx>) {
         for seg in &path.segments[..path.segments.len() - 1] {
             if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
                 self.dumper.dump_ref(data);
@@ -217,23 +217,19 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
     }
 
-    fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
+    fn process_formals(&mut self, formals: &'tcx [hir::Param<'tcx>], qualname: &str) {
         for arg in formals {
             self.visit_pat(&arg.pat);
-            let mut collector = PathCollector::new();
+            let mut collector = PathCollector::new(self.tcx);
             collector.visit_pat(&arg.pat);
 
-            for (id, ident, ..) in collector.collected_idents {
-                // FIXME(#71104) Should really be using just `node_id_to_hir_id` but
-                // some `NodeId` do not seem to have a corresponding HirId.
-                let hir_id = self.tcx.hir().opt_node_id_to_hir_id(id);
-                let typ =
-                    match hir_id.and_then(|hir_id| self.save_ctxt.tables.node_type_opt(hir_id)) {
-                        Some(s) => s.to_string(),
-                        None => continue,
-                    };
+            for (hir_id, ident, ..) in collector.collected_idents {
+                let typ = match self.save_ctxt.tables.node_type_opt(hir_id) {
+                    Some(s) => s.to_string(),
+                    None => continue,
+                };
                 if !self.span.filter_generated(ident.span) {
-                    let id = id_from_node_id(id, &self.save_ctxt);
+                    let id = id_from_hir_id(hir_id, &self.save_ctxt);
                     let span = self.span_from_span(ident.span);
 
                     self.dumper.dump_def(
@@ -260,75 +256,74 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
     fn process_method(
         &mut self,
-        sig: &'l ast::FnSig,
-        body: Option<&'l ast::Block>,
-        id: ast::NodeId,
+        sig: &'tcx hir::FnSig<'tcx>,
+        body: Option<hir::BodyId>,
+        hir_id: hir::HirId,
         ident: Ident,
-        generics: &'l ast::Generics,
-        vis: ast::Visibility,
+        generics: &'tcx hir::Generics<'tcx>,
+        vis: &hir::Visibility<'tcx>,
         span: Span,
     ) {
-        debug!("process_method: {}:{}", id, ident);
+        debug!("process_method: {}:{}", hir_id, ident);
 
         let map = &self.tcx.hir();
-        let hir_id = map.node_id_to_hir_id(id);
         self.nest_tables(map.local_def_id(hir_id), |v| {
-            if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
-                v.process_formals(&sig.decl.inputs, &method_data.qualname);
-                v.process_generic_params(&generics, &method_data.qualname, id);
+            if let Some(mut method_data) = v.save_ctxt.get_method_data(hir_id, ident, span) {
+                if let Some(body) = body {
+                    v.process_formals(map.body(body).params, &method_data.qualname);
+                }
+                v.process_generic_params(&generics, &method_data.qualname, hir_id);
 
                 method_data.value = crate::make_signature(&sig.decl, &generics);
-                method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);
+                method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
 
                 v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
             }
 
             // walk arg and return types
-            for arg in &sig.decl.inputs {
-                v.visit_ty(&arg.ty);
+            for arg in sig.decl.inputs {
+                v.visit_ty(arg);
             }
 
-            if let ast::FnRetTy::Ty(ref ret_ty) = sig.decl.output {
-                // In async functions, return types are desugared and redefined
-                // as an `impl Trait` existential type. Because of this, to match
-                // the definition paths when resolving nested types we need to
-                // start walking from the newly-created definition.
-                match sig.header.asyncness {
-                    ast::Async::Yes { return_impl_trait_id, .. } => {
-                        let hir_id = map.node_id_to_hir_id(return_impl_trait_id);
-                        v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty))
-                    }
-                    _ => v.visit_ty(ret_ty),
-                }
+            if let hir::FnRetTy::Return(ref ret_ty) = sig.decl.output {
+                v.visit_ty(ret_ty)
             }
 
             // walk the fn body
             if let Some(body) = body {
-                v.visit_block(body);
+                v.visit_expr(&map.body(body).value);
             }
         });
     }
 
-    fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
+    fn process_struct_field_def(
+        &mut self,
+        field: &'tcx hir::StructField<'tcx>,
+        parent_id: hir::HirId,
+    ) {
         let field_data = self.save_ctxt.get_field_data(field, parent_id);
         if let Some(field_data) = field_data {
-            let hir_id = self.tcx.hir().node_id_to_hir_id(field.id);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, field, hir_id), field_data);
+            self.dumper.dump_def(&access_from!(self.save_ctxt, field, field.hir_id), field_data);
         }
     }
 
     // Dump generic params bindings, then visit_generics
-    fn process_generic_params(&mut self, generics: &'l ast::Generics, prefix: &str, id: NodeId) {
-        for param in &generics.params {
+    fn process_generic_params(
+        &mut self,
+        generics: &'tcx hir::Generics<'tcx>,
+        prefix: &str,
+        id: hir::HirId,
+    ) {
+        for param in generics.params {
             match param.kind {
-                ast::GenericParamKind::Lifetime { .. } => {}
-                ast::GenericParamKind::Type { .. } => {
-                    let param_ss = param.ident.span;
+                hir::GenericParamKind::Lifetime { .. } => {}
+                hir::GenericParamKind::Type { .. } => {
+                    let param_ss = param.name.ident().span;
                     let name = escape(self.span.snippet(param_ss));
                     // Append $id to name to make sure each one is unique.
                     let qualname = format!("{}::{}${}", prefix, name, id);
                     if !self.span.filter_generated(param_ss) {
-                        let id = id_from_node_id(param.id, &self.save_ctxt);
+                        let id = id_from_hir_id(param.hir_id, &self.save_ctxt);
                         let span = self.span_from_span(param_ss);
 
                         self.dumper.dump_def(
@@ -350,7 +345,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                         );
                     }
                 }
-                ast::GenericParamKind::Const { .. } => {}
+                hir::GenericParamKind::Const { .. } => {}
             }
         }
         self.visit_generics(generics);
@@ -358,90 +353,73 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
     fn process_fn(
         &mut self,
-        item: &'l ast::Item,
-        decl: &'l ast::FnDecl,
-        header: &'l ast::FnHeader,
-        ty_params: &'l ast::Generics,
-        body: Option<&'l ast::Block>,
+        item: &'tcx hir::Item<'tcx>,
+        decl: &'tcx hir::FnDecl<'tcx>,
+        _header: &'tcx hir::FnHeader,
+        ty_params: &'tcx hir::Generics<'tcx>,
+        body: hir::BodyId,
     ) {
         let map = &self.tcx.hir();
-        let hir_id = map.node_id_to_hir_id(item.id);
-        self.nest_tables(map.local_def_id(hir_id), |v| {
+        self.nest_tables(map.local_def_id(item.hir_id), |v| {
+            let body = map.body(body);
             if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
                 down_cast_data!(fn_data, DefData, item.span);
-                v.process_formals(&decl.inputs, &fn_data.qualname);
-                v.process_generic_params(ty_params, &fn_data.qualname, item.id);
+                v.process_formals(body.params, &fn_data.qualname);
+                v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id);
 
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.hir_id), fn_data);
             }
 
-            for arg in &decl.inputs {
-                v.visit_ty(&arg.ty)
+            for arg in decl.inputs {
+                v.visit_ty(arg)
             }
 
-            if let ast::FnRetTy::Ty(ref ret_ty) = decl.output {
-                if let ast::TyKind::ImplTrait(..) = ret_ty.kind {
-                    // FIXME: Opaque type desugaring prevents us from easily
-                    // processing trait bounds. See `visit_ty` for more details.
-                } else {
-                    // In async functions, return types are desugared and redefined
-                    // as an `impl Trait` existential type. Because of this, to match
-                    // the definition paths when resolving nested types we need to
-                    // start walking from the newly-created definition.
-                    match header.asyncness {
-                        ast::Async::Yes { return_impl_trait_id, .. } => {
-                            let hir_id = map.node_id_to_hir_id(return_impl_trait_id);
-                            v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty))
-                        }
-                        _ => v.visit_ty(ret_ty),
-                    }
-                }
+            if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
+                v.visit_ty(ret_ty)
             }
 
-            walk_list!(v, visit_block, body);
+            v.visit_expr(&body.value);
         });
     }
 
     fn process_static_or_const_item(
         &mut self,
-        item: &'l ast::Item,
-        typ: &'l ast::Ty,
-        expr: Option<&'l ast::Expr>,
+        item: &'tcx hir::Item<'tcx>,
+        typ: &'tcx hir::Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
     ) {
-        let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
-        self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
+        self.nest_tables(self.tcx.hir().local_def_id(item.hir_id), |v| {
             if let Some(var_data) = v.save_ctxt.get_item_data(item) {
                 down_cast_data!(var_data, DefData, item.span);
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.hir_id), var_data);
             }
             v.visit_ty(&typ);
-            walk_list!(v, visit_expr, expr);
+            v.visit_expr(expr);
         });
     }
 
     fn process_assoc_const(
         &mut self,
-        id: ast::NodeId,
+        hir_id: hir::HirId,
         ident: Ident,
-        typ: &'l ast::Ty,
-        expr: Option<&'l ast::Expr>,
+        typ: &'tcx hir::Ty<'tcx>,
+        expr: Option<&'tcx hir::Expr<'tcx>>,
         parent_id: DefId,
-        vis: ast::Visibility,
-        attrs: &'l [Attribute],
+        vis: &hir::Visibility<'tcx>,
+        attrs: &'tcx [ast::Attribute],
     ) {
-        let hir_id = self.tcx.hir().node_id_to_hir_id(id);
         let qualname =
             format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id()));
 
         if !self.span.filter_generated(ident.span) {
-            let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt);
+            let sig = sig::assoc_const_signature(hir_id, ident.name, typ, expr, &self.save_ctxt);
             let span = self.span_from_span(ident.span);
 
             self.dumper.dump_def(
                 &access_from_vis!(self.save_ctxt, vis, hir_id),
                 Def {
                     kind: DefKind::Const,
-                    id: id_from_node_id(id, &self.save_ctxt),
+                    id: id_from_hir_id(hir_id, &self.save_ctxt),
                     span,
                     name: ident.name.to_string(),
                     qualname,
@@ -468,32 +446,32 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
     // FIXME tuple structs should generate tuple-specific data.
     fn process_struct(
         &mut self,
-        item: &'l ast::Item,
-        def: &'l ast::VariantData,
-        ty_params: &'l ast::Generics,
+        item: &'tcx hir::Item<'tcx>,
+        def: &'tcx hir::VariantData<'tcx>,
+        ty_params: &'tcx hir::Generics<'tcx>,
     ) {
         debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
-        let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
-        let qualname =
-            format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id()));
+        let qualname = format!(
+            "::{}",
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
+        );
 
         let kind = match item.kind {
-            ast::ItemKind::Struct(_, _) => DefKind::Struct,
-            ast::ItemKind::Union(_, _) => DefKind::Union,
+            hir::ItemKind::Struct(_, _) => DefKind::Struct,
+            hir::ItemKind::Union(_, _) => DefKind::Union,
             _ => unreachable!(),
         };
 
         let (value, fields) = match item.kind {
-            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), ..)
-            | ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), ..) => {
+            hir::ItemKind::Struct(hir::VariantData::Struct(ref fields, ..), ..)
+            | hir::ItemKind::Union(hir::VariantData::Struct(ref fields, ..), ..) => {
                 let include_priv_fields = !self.save_ctxt.config.pub_only;
                 let fields_str = fields
                     .iter()
-                    .enumerate()
-                    .filter_map(|(i, f)| {
+                    .filter_map(|f| {
                         if include_priv_fields || f.vis.node.is_pub() {
-                            f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
+                            Some(f.ident.to_string())
                         } else {
                             None
                         }
@@ -501,7 +479,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     .collect::<Vec<_>>()
                     .join(", ");
                 let value = format!("{} {{ {} }}", name, fields_str);
-                (value, fields.iter().map(|f| id_from_node_id(f.id, &self.save_ctxt)).collect())
+                (value, fields.iter().map(|f| id_from_hir_id(f.hir_id, &self.save_ctxt)).collect())
             }
             _ => (String::new(), vec![]),
         };
@@ -509,10 +487,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         if !self.span.filter_generated(item.ident.span) {
             let span = self.span_from_span(item.ident.span);
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item, hir_id),
+                &access_from!(self.save_ctxt, item, item.hir_id),
                 Def {
                     kind,
-                    id: id_from_node_id(item.id, &self.save_ctxt),
+                    id: id_from_hir_id(item.hir_id, &self.save_ctxt),
                     span,
                     name,
                     qualname: qualname.clone(),
@@ -522,26 +500,26 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     decl_id: None,
                     docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, &self.save_ctxt),
-                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                    attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt),
                 },
             );
         }
 
-        self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
+        self.nest_tables(self.tcx.hir().local_def_id(item.hir_id), |v| {
             for field in def.fields() {
-                v.process_struct_field_def(field, item.id);
+                v.process_struct_field_def(field, item.hir_id);
                 v.visit_ty(&field.ty);
             }
 
-            v.process_generic_params(ty_params, &qualname, item.id);
+            v.process_generic_params(ty_params, &qualname, item.hir_id);
         });
     }
 
     fn process_enum(
         &mut self,
-        item: &'l ast::Item,
-        enum_definition: &'l ast::EnumDef,
-        ty_params: &'l ast::Generics,
+        item: &'tcx hir::Item<'tcx>,
+        enum_definition: &'tcx hir::EnumDef<'tcx>,
+        ty_params: &'tcx hir::Generics<'tcx>,
     ) {
         let enum_data = self.save_ctxt.get_item_data(item);
         let enum_data = match enum_data {
@@ -550,29 +528,22 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         };
         down_cast_data!(enum_data, DefData, item.span);
 
-        let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
-        let access = access_from!(self.save_ctxt, item, hir_id);
+        let access = access_from!(self.save_ctxt, item, item.hir_id);
 
-        for variant in &enum_definition.variants {
+        for variant in enum_definition.variants {
             let name = variant.ident.name.to_string();
             let qualname = format!("{}::{}", enum_data.qualname, name);
             let name_span = variant.ident.span;
 
             match variant.data {
-                ast::VariantData::Struct(ref fields, ..) => {
-                    let fields_str = fields
-                        .iter()
-                        .enumerate()
-                        .map(|(i, f)| {
-                            f.ident.map(|i| i.to_string()).unwrap_or_else(|| i.to_string())
-                        })
-                        .collect::<Vec<_>>()
-                        .join(", ");
+                hir::VariantData::Struct(ref fields, ..) => {
+                    let fields_str =
+                        fields.iter().map(|f| f.ident.to_string()).collect::<Vec<_>>().join(", ");
                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.id, &self.save_ctxt);
-                        let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
+                        let id = id_from_hir_id(variant.id, &self.save_ctxt);
+                        let parent = Some(id_from_hir_id(item.hir_id, &self.save_ctxt));
 
                         self.dumper.dump_def(
                             &access,
@@ -589,7 +560,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                                 docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                 sig: sig::variant_signature(variant, &self.save_ctxt),
                                 attributes: lower_attributes(
-                                    variant.attrs.clone(),
+                                    variant.attrs.to_vec(),
                                     &self.save_ctxt,
                                 ),
                             },
@@ -598,7 +569,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                 }
                 ref v => {
                     let mut value = format!("{}::{}", enum_data.name, name);
-                    if let &ast::VariantData::Tuple(ref fields, _) = v {
+                    if let &hir::VariantData::Tuple(ref fields, _) = v {
                         value.push('(');
                         value.push_str(
                             &fields
@@ -611,8 +582,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     }
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.id, &self.save_ctxt);
-                        let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
+                        let id = id_from_hir_id(variant.id, &self.save_ctxt);
+                        let parent = Some(id_from_hir_id(item.hir_id, &self.save_ctxt));
 
                         self.dumper.dump_def(
                             &access,
@@ -629,7 +600,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                                 docs: self.save_ctxt.docs_for_attrs(&variant.attrs),
                                 sig: sig::variant_signature(variant, &self.save_ctxt),
                                 attributes: lower_attributes(
-                                    variant.attrs.clone(),
+                                    variant.attrs.to_vec(),
                                     &self.save_ctxt,
                                 ),
                             },
@@ -640,20 +611,20 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
             for field in variant.data.fields() {
                 self.process_struct_field_def(field, variant.id);
-                self.visit_ty(&field.ty);
+                self.visit_ty(field.ty);
             }
         }
-        self.process_generic_params(ty_params, &enum_data.qualname, item.id);
+        self.process_generic_params(ty_params, &enum_data.qualname, item.hir_id);
         self.dumper.dump_def(&access, enum_data);
     }
 
     fn process_impl(
         &mut self,
-        item: &'l ast::Item,
-        generics: &'l ast::Generics,
-        trait_ref: &'l Option<ast::TraitRef>,
-        typ: &'l ast::Ty,
-        impl_items: &'l [P<ast::AssocItem>],
+        item: &'tcx hir::Item<'tcx>,
+        generics: &'tcx hir::Generics<'tcx>,
+        trait_ref: &'tcx Option<hir::TraitRef<'tcx>>,
+        typ: &'tcx hir::Ty<'tcx>,
+        impl_items: &'tcx [hir::ImplItemRef<'tcx>],
     ) {
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
             if !self.span.filter_generated(item.span) {
@@ -667,46 +638,48 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
 
         let map = &self.tcx.hir();
-        let hir_id = map.node_id_to_hir_id(item.id);
-        self.nest_tables(map.local_def_id(hir_id), |v| {
+        self.nest_tables(map.local_def_id(item.hir_id), |v| {
             v.visit_ty(&typ);
             if let &Some(ref trait_ref) = trait_ref {
-                v.process_path(trait_ref.ref_id, &trait_ref.path);
+                v.process_path(trait_ref.hir_ref_id, &trait_ref.path);
             }
-            v.process_generic_params(generics, "", item.id);
+            v.process_generic_params(generics, "", item.hir_id);
             for impl_item in impl_items {
-                v.process_impl_item(impl_item, map.local_def_id(hir_id).to_def_id());
+                v.process_impl_item(
+                    map.impl_item(impl_item.id),
+                    map.local_def_id(item.hir_id).to_def_id(),
+                );
             }
         });
     }
 
     fn process_trait(
         &mut self,
-        item: &'l ast::Item,
-        generics: &'l ast::Generics,
-        trait_refs: &'l ast::GenericBounds,
-        methods: &'l [P<ast::AssocItem>],
+        item: &'tcx hir::Item<'tcx>,
+        generics: &'tcx hir::Generics<'tcx>,
+        trait_refs: hir::GenericBounds<'tcx>,
+        methods: &'tcx [hir::TraitItemRef],
     ) {
         let name = item.ident.to_string();
         let qualname = format!(
             "::{}",
-            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id())
+            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
         );
         let mut val = name.clone();
         if !generics.params.is_empty() {
-            val.push_str(&generic_params_to_string(&generics.params));
+            val.push_str(&generic_params_to_string(generics.params));
         }
         if !trait_refs.is_empty() {
             val.push_str(": ");
             val.push_str(&bounds_to_string(trait_refs));
         }
         if !self.span.filter_generated(item.ident.span) {
-            let id = id_from_node_id(item.id, &self.save_ctxt);
+            let id = id_from_hir_id(item.hir_id, &self.save_ctxt);
             let span = self.span_from_span(item.ident.span);
-            let children = methods.iter().map(|i| id_from_node_id(i.id, &self.save_ctxt)).collect();
-            let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
+            let children =
+                methods.iter().map(|i| id_from_hir_id(i.id.hir_id, &self.save_ctxt)).collect();
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item, hir_id),
+                &access_from!(self.save_ctxt, item, item.hir_id),
                 Def {
                     kind: DefKind::Trait,
                     id,
@@ -719,7 +692,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     decl_id: None,
                     docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, &self.save_ctxt),
-                    attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                    attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt),
                 },
             );
         }
@@ -727,12 +700,12 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         // super-traits
         for super_bound in trait_refs.iter() {
             let trait_ref = match *super_bound {
-                ast::GenericBound::Trait(ref trait_ref, _) => trait_ref,
-                ast::GenericBound::Outlives(..) => continue,
+                hir::GenericBound::Trait(ref trait_ref, _) => trait_ref,
+                hir::GenericBound::Outlives(..) => continue,
             };
 
             let trait_ref = &trait_ref.trait_ref;
-            if let Some(id) = self.lookup_def_id(trait_ref.ref_id) {
+            if let Some(id) = self.lookup_def_id(trait_ref.hir_ref_id) {
                 let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
                 if !self.span.filter_generated(sub_span) {
                     let span = self.span_from_span(sub_span);
@@ -746,60 +719,57 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                         kind: RelationKind::SuperTrait,
                         span,
                         from: id_from_def_id(id),
-                        to: id_from_node_id(item.id, &self.save_ctxt),
+                        to: id_from_hir_id(item.hir_id, &self.save_ctxt),
                     });
                 }
             }
         }
 
         // walk generics and methods
-        self.process_generic_params(generics, &qualname, item.id);
+        self.process_generic_params(generics, &qualname, item.hir_id);
         for method in methods {
             let map = &self.tcx.hir();
-            self.process_trait_item(method, map.local_def_id_from_node_id(item.id).to_def_id())
+            self.process_trait_item(
+                map.trait_item(method.id),
+                map.local_def_id(item.hir_id).to_def_id(),
+            )
         }
     }
 
-    // `item` is the module in question, represented as an item.
-    fn process_mod(&mut self, item: &ast::Item) {
+    // `item` is the module in question, represented as an( item.
+    fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
         if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
             down_cast_data!(mod_data, DefData, item.span);
-            let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), mod_data);
+            self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.hir_id), mod_data);
         }
     }
 
-    fn dump_path_ref(&mut self, id: NodeId, path: &ast::Path) {
+    fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::Path<'tcx>) {
         let path_data = self.save_ctxt.get_path_data(id, path);
         if let Some(path_data) = path_data {
             self.dumper.dump_ref(path_data);
         }
     }
 
-    fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
+    fn dump_path_segment_ref(&mut self, id: hir::HirId, segment: &hir::PathSegment<'tcx>) {
+        let segment_data = self.save_ctxt.get_path_segment_data_with_id(segment, id);
+        if let Some(segment_data) = segment_data {
+            self.dumper.dump_ref(segment_data);
+        }
+    }
+
+    fn process_path(&mut self, id: hir::HirId, path: &'tcx hir::Path<'tcx>) {
         if self.span.filter_generated(path.span) {
             return;
         }
         self.dump_path_ref(id, path);
 
         // Type arguments
-        for seg in &path.segments {
+        for seg in path.segments {
             if let Some(ref generic_args) = seg.args {
-                match **generic_args {
-                    ast::GenericArgs::AngleBracketed(ref data) => {
-                        for arg in &data.args {
-                            if let ast::AngleBracketedArg::Arg(ast::GenericArg::Type(ty)) = arg {
-                                self.visit_ty(ty);
-                            }
-                        }
-                    }
-                    ast::GenericArgs::Parenthesized(ref data) => {
-                        for t in &data.inputs {
-                            self.visit_ty(t);
-                        }
-                        if let ast::FnRetTy::Ty(ty) = &data.output {
-                            self.visit_ty(ty);
-                        }
+                for arg in generic_args.args {
+                    if let hir::GenericArg::Type(ref ty) = arg {
+                        self.visit_ty(ty);
                     }
                 }
             }
@@ -810,14 +780,16 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
     fn process_struct_lit(
         &mut self,
-        ex: &'l ast::Expr,
-        path: &'l ast::Path,
-        fields: &'l [ast::Field],
-        variant: &'l ty::VariantDef,
-        base: &'l Option<P<ast::Expr>>,
+        ex: &'tcx hir::Expr<'tcx>,
+        path: &'tcx hir::QPath<'tcx>,
+        fields: &'tcx [hir::Field<'tcx>],
+        variant: &'tcx ty::VariantDef,
+        base: Option<&'tcx hir::Expr<'tcx>>,
     ) {
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
-            self.write_sub_paths_truncated(path);
+            if let hir::QPath::Resolved(_, path) = path {
+                self.write_sub_paths_truncated(path);
+            }
             down_cast_data!(struct_lit_data, RefData, ex.span);
             if !generated_code(ex.span) {
                 self.dumper.dump_ref(struct_lit_data);
@@ -837,9 +809,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
     fn process_method_call(
         &mut self,
-        ex: &'l ast::Expr,
-        seg: &'l ast::PathSegment,
-        args: &'l [P<ast::Expr>],
+        ex: &'tcx hir::Expr<'tcx>,
+        seg: &'tcx hir::PathSegment<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) {
         debug!("process_method_call {:?} {:?}", ex, ex.span);
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
@@ -850,13 +822,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
 
         // Explicit types in the turbo-fish.
-        if let Some(ref generic_args) = seg.args {
-            if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
-                for arg in &data.args {
-                    if let ast::AngleBracketedArg::Arg(ast::GenericArg::Type(ty)) = arg {
-                        self.visit_ty(ty)
-                    };
-                }
+        if let Some(generic_args) = seg.args {
+            for arg in generic_args.args {
+                if let hir::GenericArg::Type(ty) = arg {
+                    self.visit_ty(&ty)
+                };
             }
         }
 
@@ -864,19 +834,18 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         walk_list!(self, visit_expr, args);
     }
 
-    fn process_pat(&mut self, p: &'l ast::Pat) {
+    fn process_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
         match p.kind {
-            PatKind::Struct(ref _path, ref fields, _) => {
+            hir::PatKind::Struct(ref _path, fields, _) => {
                 // FIXME do something with _path?
-                let hir_id = self.tcx.hir().node_id_to_hir_id(p.id);
-                let adt = match self.save_ctxt.tables.node_type_opt(hir_id) {
+                let adt = match self.save_ctxt.tables.node_type_opt(p.hir_id) {
                     Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
                     _ => {
-                        visit::walk_pat(self, p);
+                        intravisit::walk_pat(self, p);
                         return;
                     }
                 };
-                let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.id));
+                let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.hir_id));
 
                 for field in fields {
                     if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
@@ -892,22 +861,22 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     self.visit_pat(&field.pat);
                 }
             }
-            _ => visit::walk_pat(self, p),
+            _ => intravisit::walk_pat(self, p),
         }
     }
 
-    fn process_var_decl(&mut self, pat: &'l ast::Pat) {
+    fn process_var_decl(&mut self, pat: &'tcx hir::Pat<'tcx>) {
         // The pattern could declare multiple new vars,
         // we must walk the pattern and collect them all.
-        let mut collector = PathCollector::new();
+        let mut collector = PathCollector::new(self.tcx);
         collector.visit_pat(&pat);
         self.visit_pat(&pat);
 
         // Process collected paths.
         for (id, ident, _) in collector.collected_idents {
-            match self.save_ctxt.get_path_res(id) {
+            let res = self.save_ctxt.get_path_res(id);
+            match res {
                 Res::Local(hir_id) => {
-                    let id = self.tcx.hir().hir_id_to_node_id(hir_id);
                     let typ = self
                         .save_ctxt
                         .tables
@@ -917,8 +886,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
 
                     // Rust uses the id of the pattern for var lookups, so we'll use it too.
                     if !self.span.filter_generated(ident.span) {
-                        let qualname = format!("{}${}", ident.to_string(), id);
-                        let id = id_from_node_id(id, &self.save_ctxt);
+                        let qualname = format!("{}${}", ident.to_string(), hir_id);
+                        let id = id_from_hir_id(hir_id, &self.save_ctxt);
                         let span = self.span_from_span(ident.span);
 
                         self.dumper.dump_def(
@@ -951,7 +920,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     _,
                 )
                 | Res::SelfTy(..) => {
-                    self.dump_path_ref(id, &ast::Path::from_ident(ident));
+                    self.dump_path_segment_ref(id, &hir::PathSegment::from_ident(ident));
                 }
                 def => {
                     error!("unexpected definition kind when processing collected idents: {:?}", def)
@@ -960,7 +929,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
 
         for (id, ref path) in collector.collected_paths {
-            self.process_path(id, path);
+            if let hir::QPath::Resolved(_, path) = path {
+                self.process_path(id, path);
+            }
         }
     }
 
@@ -1007,45 +978,49 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         // }
     }
 
-    fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId) {
+    fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) {
         self.process_macro_use(trait_item.span);
         let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
-            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            hir::TraitItemKind::Const(ref ty, body) => {
+                let body = body.map(|b| &self.tcx.hir().body(b).value);
+                let respan = respan(vis_span, hir::VisibilityKind::Public);
                 self.process_assoc_const(
-                    trait_item.id,
+                    trait_item.hir_id,
                     trait_item.ident,
                     &ty,
-                    expr.as_ref().map(|e| &**e),
+                    body,
                     trait_id,
-                    respan(vis_span, ast::VisibilityKind::Public),
+                    &respan,
                     &trait_item.attrs,
                 );
             }
-            ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => {
+            hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
+                let body =
+                    if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None };
+                let respan = respan(vis_span, hir::VisibilityKind::Public);
                 self.process_method(
                     sig,
-                    body.as_ref().map(|x| &**x),
-                    trait_item.id,
+                    body,
+                    trait_item.hir_id,
                     trait_item.ident,
-                    generics,
-                    respan(vis_span, ast::VisibilityKind::Public),
+                    &trait_item.generics,
+                    &respan,
                     trait_item.span,
                 );
             }
-            ast::AssocItemKind::TyAlias(_, _, ref bounds, ref default_ty) => {
+            hir::TraitItemKind::Type(ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!(
                     "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(trait_item.id).to_def_id()
-                    )
+                    self.tcx
+                        .def_path_str(self.tcx.hir().local_def_id(trait_item.hir_id).to_def_id())
                 );
 
                 if !self.span.filter_generated(trait_item.ident.span) {
                     let span = self.span_from_span(trait_item.ident.span);
-                    let id = id_from_node_id(trait_item.id, &self.save_ctxt);
+                    let id = id_from_hir_id(trait_item.hir_id, &self.save_ctxt);
 
                     self.dumper.dump_def(
                         &Access { public: true, reachable: true },
@@ -1061,13 +1036,16 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                             decl_id: None,
                             docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
                             sig: sig::assoc_type_signature(
-                                trait_item.id,
+                                trait_item.hir_id,
                                 trait_item.ident,
                                 Some(bounds),
                                 default_ty.as_ref().map(|ty| &**ty),
                                 &self.save_ctxt,
                             ),
-                            attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt),
+                            attributes: lower_attributes(
+                                trait_item.attrs.to_vec(),
+                                &self.save_ctxt,
+                            ),
                         },
                     );
                 }
@@ -1076,98 +1054,122 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     self.visit_ty(default_ty)
                 }
             }
-            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
-    fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) {
+    fn process_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>, impl_id: DefId) {
         self.process_macro_use(impl_item.span);
         match impl_item.kind {
-            ast::AssocItemKind::Const(_, ref ty, ref expr) => {
+            hir::ImplItemKind::Const(ref ty, body) => {
+                let body = self.tcx.hir().body(body);
                 self.process_assoc_const(
-                    impl_item.id,
+                    impl_item.hir_id,
                     impl_item.ident,
                     &ty,
-                    expr.as_deref(),
+                    Some(&body.value),
                     impl_id,
-                    impl_item.vis.clone(),
+                    &impl_item.vis,
                     &impl_item.attrs,
                 );
             }
-            ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => {
+            hir::ImplItemKind::Fn(ref sig, body) => {
                 self.process_method(
                     sig,
-                    body.as_deref(),
-                    impl_item.id,
+                    Some(body),
+                    impl_item.hir_id,
                     impl_item.ident,
-                    generics,
-                    impl_item.vis.clone(),
+                    &impl_item.generics,
+                    &impl_item.vis,
                     impl_item.span,
                 );
             }
-            ast::AssocItemKind::TyAlias(_, _, _, None) => {}
-            ast::AssocItemKind::TyAlias(_, _, _, Some(ref ty)) => {
+            hir::ImplItemKind::OpaqueTy(..) => {}
+            hir::ImplItemKind::TyAlias(ref ty) => {
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
                 // trait.
                 self.visit_ty(ty)
             }
-            ast::AssocItemKind::MacCall(_) => {}
         }
     }
 
-    /// Dumps imports in a use tree recursively.
-    ///
-    /// A use tree is an import that may contain nested braces (RFC 2128). The `use_tree` parameter
-    /// is the current use tree under scrutiny, while `id` and `prefix` are its corresponding node
-    /// ID and path. `root_item` is the topmost use tree in the hierarchy.
-    ///
-    /// If `use_tree` is a simple or glob import, it is dumped into the analysis data. Otherwise,
-    /// each child use tree is dumped recursively.
-    fn process_use_tree(
-        &mut self,
-        use_tree: &'l ast::UseTree,
-        id: NodeId,
-        root_item: &'l ast::Item,
-        prefix: &ast::Path,
-    ) {
-        let path = &use_tree.prefix;
-
-        // The access is calculated using the current tree ID, but with the root tree's visibility
-        // (since nested trees don't have their own visibility).
-        let hir_id = self.tcx.hir().node_id_to_hir_id(id);
-        let access = access_from!(self.save_ctxt, root_item, hir_id);
-
-        // The parent `DefId` of a given use tree is always the enclosing item.
-        let parent = self
-            .save_ctxt
-            .tcx
-            .hir()
-            .opt_local_def_id_from_node_id(id)
-            .and_then(|id| self.save_ctxt.tcx.parent(id.to_def_id()))
-            .map(id_from_def_id);
-
-        match use_tree.kind {
-            ast::UseTreeKind::Simple(alias, ..) => {
-                let ident = use_tree.ident();
-                let path = ast::Path {
-                    segments: prefix.segments.iter().chain(path.segments.iter()).cloned().collect(),
-                    span: path.span,
-                };
+    pub(crate) fn process_crate(&mut self, krate: &'tcx hir::Crate<'tcx>) {
+        let id = hir::CRATE_HIR_ID;
+        let qualname =
+            format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id()));
+
+        let sm = self.tcx.sess.source_map();
+        let filename = sm.span_to_filename(krate.item.span);
+        let data_id = id_from_hir_id(id, &self.save_ctxt);
+        let children = krate
+            .item
+            .module
+            .item_ids
+            .iter()
+            .map(|i| id_from_hir_id(i.id, &self.save_ctxt))
+            .collect();
+        let span = self.span_from_span(krate.item.span);
+
+        self.dumper.dump_def(
+            &Access { public: true, reachable: true },
+            Def {
+                kind: DefKind::Mod,
+                id: data_id,
+                name: String::new(),
+                qualname,
+                span,
+                value: filename.to_string(),
+                children,
+                parent: None,
+                decl_id: None,
+                docs: self.save_ctxt.docs_for_attrs(krate.item.attrs),
+                sig: None,
+                attributes: lower_attributes(krate.item.attrs.to_owned(), &self.save_ctxt),
+            },
+        );
+        intravisit::walk_crate(self, krate);
+    }
+
+    fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
+        for bound in bounds {
+            if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
+                self.process_path(trait_ref.trait_ref.hir_ref_id, &trait_ref.trait_ref.path)
+            }
+        }
+    }
+}
 
+impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
+        self.process_macro_use(item.span);
+        match item.kind {
+            hir::ItemKind::Use(path, hir::UseKind::Single) => {
                 let sub_span = path.segments.last().unwrap().ident.span;
                 if !self.span.filter_generated(sub_span) {
-                    let ref_id = self.lookup_def_id(id).map(id_from_def_id);
-                    let alias_span = alias.map(|i| self.span_from_span(i.span));
+                    let access = access_from!(self.save_ctxt, item, item.hir_id);
+                    let ref_id = self.lookup_def_id(item.hir_id).map(id_from_def_id);
                     let span = self.span_from_span(sub_span);
+                    let parent = self
+                        .save_ctxt
+                        .tcx
+                        .hir()
+                        .opt_local_def_id(item.hir_id)
+                        .and_then(|id| self.save_ctxt.tcx.parent(id.to_def_id()))
+                        .map(id_from_def_id);
                     self.dumper.import(
                         &access,
                         Import {
                             kind: ImportKind::Use,
                             ref_id,
                             span,
-                            alias_span,
-                            name: ident.to_string(),
+                            alias_span: None,
+                            name: item.ident.to_string(),
                             value: String::new(),
                             parent,
                         },
@@ -1175,25 +1177,27 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     self.write_sub_paths_truncated(&path);
                 }
             }
-            ast::UseTreeKind::Glob => {
-                let path = ast::Path {
-                    segments: prefix.segments.iter().chain(path.segments.iter()).cloned().collect(),
-                    span: path.span,
-                };
-
+            hir::ItemKind::Use(path, hir::UseKind::Glob) => {
                 // Make a comma-separated list of names of imported modules.
-                let def_id = self.tcx.hir().local_def_id_from_node_id(id);
+                let def_id = self.tcx.hir().local_def_id(item.hir_id);
                 let names = self.tcx.names_imported_by_glob_use(def_id);
                 let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
 
                 // Otherwise it's a span with wrong macro expansion info, which
                 // we don't want to track anyway, since it's probably macro-internal `use`
                 if let Some(sub_span) =
-                    self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star))
+                    self.span.sub_span_of_token(item.span, token::BinOp(token::Star))
                 {
-                    if !self.span.filter_generated(use_tree.span) {
+                    if !self.span.filter_generated(item.span) {
+                        let access = access_from!(self.save_ctxt, item, item.hir_id);
                         let span = self.span_from_span(sub_span);
-
+                        let parent = self
+                            .save_ctxt
+                            .tcx
+                            .hir()
+                            .opt_local_def_id(item.hir_id)
+                            .and_then(|id| self.save_ctxt.tcx.parent(id.to_def_id()))
+                            .map(id_from_def_id);
                         self.dumper.import(
                             &access,
                             Import {
@@ -1210,73 +1214,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     }
                 }
             }
-            ast::UseTreeKind::Nested(ref nested_items) => {
-                let prefix = ast::Path {
-                    segments: prefix.segments.iter().chain(path.segments.iter()).cloned().collect(),
-                    span: path.span,
-                };
-                for &(ref tree, id) in nested_items {
-                    self.process_use_tree(tree, id, root_item, &prefix);
-                }
-            }
-        }
-    }
-
-    fn process_bounds(&mut self, bounds: &'l ast::GenericBounds) {
-        for bound in bounds {
-            if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
-                self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
-            }
-        }
-    }
-}
-
-impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
-    fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) {
-        // Since we handle explicit modules ourselves in visit_item, this should
-        // only get called for the root module of a crate.
-        assert_eq!(id, ast::CRATE_NODE_ID);
-
-        let qualname = format!(
-            "::{}",
-            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id).to_def_id())
-        );
-
-        let sm = self.tcx.sess.source_map();
-        let filename = sm.span_to_filename(span);
-        let data_id = id_from_node_id(id, &self.save_ctxt);
-        let children = m.items.iter().map(|i| id_from_node_id(i.id, &self.save_ctxt)).collect();
-        let span = self.span_from_span(span);
-
-        self.dumper.dump_def(
-            &Access { public: true, reachable: true },
-            Def {
-                kind: DefKind::Mod,
-                id: data_id,
-                name: String::new(),
-                qualname,
-                span,
-                value: filename.to_string(),
-                children,
-                parent: None,
-                decl_id: None,
-                docs: self.save_ctxt.docs_for_attrs(attrs),
-                sig: None,
-                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
-            },
-        );
-        visit::walk_mod(self, m);
-    }
-
-    fn visit_item(&mut self, item: &'l ast::Item) {
-        use rustc_ast::ast::ItemKind::*;
-        self.process_macro_use(item.span);
-        match item.kind {
-            Use(ref use_tree) => {
-                let prefix = ast::Path { segments: vec![], span: DUMMY_SP };
-                self.process_use_tree(use_tree, item.id, item, &prefix);
-            }
-            ExternCrate(_) => {
+            hir::ItemKind::ExternCrate(_) => {
                 let name_span = item.ident.span;
                 if !self.span.filter_generated(name_span) {
                     let span = self.span_from_span(name_span);
@@ -1284,7 +1222,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                         .save_ctxt
                         .tcx
                         .hir()
-                        .opt_local_def_id_from_node_id(item.id)
+                        .opt_local_def_id(item.hir_id)
                         .and_then(|id| self.save_ctxt.tcx.parent(id.to_def_id()))
                         .map(id_from_def_id);
                     self.dumper.import(
@@ -1301,43 +1239,44 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     );
                 }
             }
-            Fn(_, ref sig, ref ty_params, ref body) => {
-                self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref())
+            hir::ItemKind::Fn(ref sig, ref ty_params, body) => {
+                self.process_fn(item, sig.decl, &sig.header, ty_params, body)
+            }
+            hir::ItemKind::Static(ref typ, _, body) => {
+                let body = self.tcx.hir().body(body);
+                self.process_static_or_const_item(item, typ, &body.value)
+            }
+            hir::ItemKind::Const(ref typ, body) => {
+                let body = self.tcx.hir().body(body);
+                self.process_static_or_const_item(item, typ, &body.value)
             }
-            Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
-            Const(_, ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
-            Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
+            hir::ItemKind::Struct(ref def, ref ty_params)
+            | hir::ItemKind::Union(ref def, ref ty_params) => {
                 self.process_struct(item, def, ty_params)
             }
-            Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => {
+            hir::ItemKind::Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
+            hir::ItemKind::Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => {
                 self.process_impl(item, generics, of_trait, &self_ty, items)
             }
-            Trait(_, _, ref generics, ref trait_refs, ref methods) => {
+            hir::ItemKind::Trait(_, _, ref generics, ref trait_refs, methods) => {
                 self.process_trait(item, generics, trait_refs, methods)
             }
-            Mod(ref m) => {
+            hir::ItemKind::Mod(ref m) => {
                 self.process_mod(item);
-                visit::walk_mod(self, m);
+                intravisit::walk_mod(self, m, item.hir_id);
             }
-            TyAlias(_, ref ty_params, _, ref ty) => {
+            hir::ItemKind::TyAlias(ty, ref generics) => {
                 let qualname = format!(
                     "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
+                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
                 );
-                let value = match ty {
-                    Some(ty) => ty_to_string(&ty),
-                    None => "_".to_string(),
-                };
+                let value = ty_to_string(&ty);
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
-                    let id = id_from_node_id(item.id, &self.save_ctxt);
-                    let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
+                    let id = id_from_hir_id(item.hir_id, &self.save_ctxt);
 
                     self.dumper.dump_def(
-                        &access_from!(self.save_ctxt, item, hir_id),
+                        &access_from!(self.save_ctxt, item, item.hir_id),
                         Def {
                             kind: DefKind::Type,
                             id,
@@ -1350,52 +1289,51 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                             decl_id: None,
                             docs: self.save_ctxt.docs_for_attrs(&item.attrs),
                             sig: sig::item_signature(item, &self.save_ctxt),
-                            attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                            attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt),
                         },
                     );
                 }
 
-                walk_list!(self, visit_ty, ty);
-                self.process_generic_params(ty_params, &qualname, item.id);
+                self.visit_ty(ty);
+                self.process_generic_params(generics, &qualname, item.hir_id);
             }
-            MacCall(_) => (),
-            _ => visit::walk_item(self, item),
+            _ => intravisit::walk_item(self, item),
         }
     }
 
-    fn visit_generics(&mut self, generics: &'l ast::Generics) {
-        for param in &generics.params {
+    fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
+        for param in generics.params {
             match param.kind {
-                ast::GenericParamKind::Lifetime { .. } => {}
-                ast::GenericParamKind::Type { ref default, .. } => {
-                    self.process_bounds(&param.bounds);
+                hir::GenericParamKind::Lifetime { .. } => {}
+                hir::GenericParamKind::Type { ref default, .. } => {
+                    self.process_bounds(param.bounds);
                     if let Some(ref ty) = default {
-                        self.visit_ty(&ty);
+                        self.visit_ty(ty);
                     }
                 }
-                ast::GenericParamKind::Const { ref ty } => {
-                    self.process_bounds(&param.bounds);
-                    self.visit_ty(&ty);
+                hir::GenericParamKind::Const { ref ty } => {
+                    self.process_bounds(param.bounds);
+                    self.visit_ty(ty);
                 }
             }
         }
-        for pred in &generics.where_clause.predicates {
-            if let ast::WherePredicate::BoundPredicate(ref wbp) = *pred {
-                self.process_bounds(&wbp.bounds);
-                self.visit_ty(&wbp.bounded_ty);
+        for pred in generics.where_clause.predicates {
+            if let hir::WherePredicate::BoundPredicate(ref wbp) = *pred {
+                self.process_bounds(wbp.bounds);
+                self.visit_ty(wbp.bounded_ty);
             }
         }
     }
 
-    fn visit_ty(&mut self, t: &'l ast::Ty) {
+    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
         self.process_macro_use(t.span);
         match t.kind {
-            ast::TyKind::Path(_, ref path) => {
+            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
                 if generated_code(t.span) {
                     return;
                 }
 
-                if let Some(id) = self.lookup_def_id(t.id) {
+                if let Some(id) = self.lookup_def_id(t.hir_id) {
                     let sub_span = path.segments.last().unwrap().ident.span;
                     let span = self.span_from_span(sub_span);
                     self.dumper.dump_ref(Ref {
@@ -1406,57 +1344,37 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 }
 
                 self.write_sub_paths_truncated(path);
-                visit::walk_path(self, path);
+                intravisit::walk_path(self, path);
             }
-            ast::TyKind::Array(ref element, ref length) => {
-                self.visit_ty(element);
-                let hir_id = self.tcx.hir().node_id_to_hir_id(length.id);
-                self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
-                    v.visit_expr(&length.value)
+            hir::TyKind::Array(ref ty, ref anon_const) => {
+                self.visit_ty(ty);
+                let map = self.tcx.hir();
+                self.nest_tables(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
+                    v.visit_expr(&map.body(anon_const.body).value)
                 });
             }
-            ast::TyKind::ImplTrait(id, ref bounds) => {
-                // FIXME: As of writing, the opaque type lowering introduces
-                // another DefPath scope/segment (used to declare the resulting
-                // opaque type item).
-                // However, the synthetic scope does *not* have associated
-                // typeck tables, which means we can't nest it and we fire an
-                // assertion when resolving the qualified type paths in trait
-                // bounds...
-                // This will panic if called on return type `impl Trait`, which
-                // we guard against in `process_fn`.
-                // FIXME(#71104) Should really be using just `node_id_to_hir_id` but
-                // some `NodeId` do not seem to have a corresponding HirId.
-                if let Some(hir_id) = self.tcx.hir().opt_node_id_to_hir_id(id) {
-                    self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
-                        v.process_bounds(bounds)
-                    });
-                }
-            }
-            _ => visit::walk_ty(self, t),
+            _ => intravisit::walk_ty(self, t),
         }
     }
 
-    fn visit_expr(&mut self, ex: &'l ast::Expr) {
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         debug!("visit_expr {:?}", ex.kind);
         self.process_macro_use(ex.span);
         match ex.kind {
-            ast::ExprKind::Struct(ref path, ref fields, ref base) => {
-                let expr_hir_id = self.save_ctxt.tcx.hir().node_id_to_hir_id(ex.id);
-                let hir_expr = self.save_ctxt.tcx.hir().expect_expr(expr_hir_id);
+            hir::ExprKind::Struct(ref path, ref fields, ref base) => {
+                let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id);
                 let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
                     Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
                     _ => {
-                        visit::walk_expr(self, ex);
+                        intravisit::walk_expr(self, ex);
                         return;
                     }
                 };
-                let node_id = self.save_ctxt.tcx.hir().hir_id_to_node_id(hir_expr.hir_id);
-                let res = self.save_ctxt.get_path_res(node_id);
-                self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), base)
+                let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
+                self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base)
             }
-            ast::ExprKind::MethodCall(ref seg, ref args) => self.process_method_call(ex, seg, args),
-            ast::ExprKind::Field(ref sub_ex, _) => {
+            hir::ExprKind::MethodCall(ref seg, _, args) => self.process_method_call(ex, seg, args),
+            hir::ExprKind::Field(ref sub_ex, _) => {
                 self.visit_expr(&sub_ex);
 
                 if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
@@ -1466,71 +1384,62 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     }
                 }
             }
-            ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => {
-                let id = format!("${}", ex.id);
+            hir::ExprKind::Closure(_, ref decl, body, _fn_decl_span, _) => {
+                let id = format!("${}", ex.hir_id);
 
                 // walk arg and return types
-                for arg in &decl.inputs {
-                    self.visit_ty(&arg.ty);
+                for ty in decl.inputs {
+                    self.visit_ty(ty);
                 }
 
-                if let ast::FnRetTy::Ty(ref ret_ty) = decl.output {
-                    self.visit_ty(&ret_ty);
+                if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
+                    self.visit_ty(ret_ty);
                 }
 
                 // walk the body
-                let hir_id = self.tcx.hir().node_id_to_hir_id(ex.id);
-                self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
-                    v.process_formals(&decl.inputs, &id);
-                    v.visit_expr(body)
+                let map = self.tcx.hir();
+                self.nest_tables(self.tcx.hir().local_def_id(ex.hir_id), |v| {
+                    let body = map.body(body);
+                    v.process_formals(body.params, &id);
+                    v.visit_expr(&body.value)
                 });
             }
-            ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) => {
-                self.process_var_decl(pattern);
-                debug!("for loop, walk sub-expr: {:?}", subexpression.kind);
-                self.visit_expr(subexpression);
-                visit::walk_block(self, block);
-            }
-            ast::ExprKind::Let(ref pat, ref scrutinee) => {
-                self.process_var_decl(pat);
-                self.visit_expr(scrutinee);
-            }
-            ast::ExprKind::Repeat(ref element, ref count) => {
-                self.visit_expr(element);
-                let hir_id = self.tcx.hir().node_id_to_hir_id(count.id);
-                self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| {
-                    v.visit_expr(&count.value)
+            hir::ExprKind::Repeat(ref expr, ref anon_const) => {
+                self.visit_expr(expr);
+                let map = self.tcx.hir();
+                self.nest_tables(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
+                    v.visit_expr(&map.body(anon_const.body).value)
                 });
             }
             // In particular, we take this branch for call and path expressions,
             // where we'll index the idents involved just by continuing to walk.
-            _ => visit::walk_expr(self, ex),
+            _ => intravisit::walk_expr(self, ex),
         }
     }
 
-    fn visit_pat(&mut self, p: &'l ast::Pat) {
+    fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
         self.process_macro_use(p.span);
         self.process_pat(p);
     }
 
-    fn visit_arm(&mut self, arm: &'l ast::Arm) {
+    fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
         self.process_var_decl(&arm.pat);
-        if let Some(expr) = &arm.guard {
+        if let Some(hir::Guard::If(expr)) = &arm.guard {
             self.visit_expr(expr);
         }
         self.visit_expr(&arm.body);
     }
 
-    fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) {
+    fn visit_path(&mut self, p: &'tcx hir::Path<'tcx>, id: hir::HirId) {
         self.process_path(id, p);
     }
 
-    fn visit_stmt(&mut self, s: &'l ast::Stmt) {
+    fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
         self.process_macro_use(s.span);
-        visit::walk_stmt(self, s)
+        intravisit::walk_stmt(self, s)
     }
 
-    fn visit_local(&mut self, l: &'l ast::Local) {
+    fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
         self.process_macro_use(l.span);
         self.process_var_decl(&l.pat);
 
@@ -1539,29 +1448,27 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
         walk_list!(self, visit_expr, &l.init);
     }
 
-    fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
-        let hir_id = self.tcx.hir().node_id_to_hir_id(item.id);
-        let access = access_from!(self.save_ctxt, item, hir_id);
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
+        let access = access_from!(self.save_ctxt, item, item.hir_id);
 
         match item.kind {
-            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
-                let decl = &sig.decl;
+            hir::ForeignItemKind::Fn(decl, _, ref generics) => {
                 if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(fn_data, DefData, item.span);
 
-                    self.process_generic_params(generics, &fn_data.qualname, item.id);
+                    self.process_generic_params(generics, &fn_data.qualname, item.hir_id);
                     self.dumper.dump_def(&access, fn_data);
                 }
 
-                for arg in &decl.inputs {
-                    self.visit_ty(&arg.ty);
+                for ty in decl.inputs {
+                    self.visit_ty(ty);
                 }
 
-                if let ast::FnRetTy::Ty(ref ret_ty) = decl.output {
-                    self.visit_ty(&ret_ty);
+                if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
+                    self.visit_ty(ret_ty);
                 }
             }
-            ast::ForeignItemKind::Static(ref ty, _, _) => {
+            hir::ForeignItemKind::Static(ref ty, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
                     self.dumper.dump_def(&access, var_data);
@@ -1569,13 +1476,12 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
 
                 self.visit_ty(ty);
             }
-            ast::ForeignItemKind::TyAlias(..) => {
+            hir::ForeignItemKind::Type => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
                     self.dumper.dump_def(&access, var_data);
                 }
             }
-            ast::ForeignItemKind::MacCall(..) => {}
         }
     }
 }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 3bd68a9c656..8c7731c18e9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -9,14 +9,16 @@ mod dumper;
 mod span_utils;
 mod sig;
 
-use rustc_ast::ast::{self, Attribute, NodeId, PatKind, DUMMY_NODE_ID};
+use rustc_ast::ast::{self};
 use rustc_ast::util::comments::strip_doc_comment_decoration;
-use rustc_ast::visit::{self, Visitor};
-use rustc_ast_pretty::pprust::{self, param_to_string, ty_to_string};
+use rustc_ast_pretty::pprust::attribute_to_string;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Node;
+use rustc_hir_pretty::ty_to_string;
+use rustc_middle::hir::map::Map;
 use rustc_middle::middle::cstore::ExternCrate;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
@@ -129,34 +131,32 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         result
     }
 
-    pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
-        let qualname = format!(
-            "::{}",
-            self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id())
-        );
+    pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> {
+        let def_id = self.tcx.hir().local_def_id(item.hir_id).to_def_id();
+        let qualname = format!("::{}", self.tcx.def_path_str(def_id));
         match item.kind {
-            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
+            hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
                 filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
                     kind: DefKind::ForeignFunction,
-                    id: id_from_node_id(item.id, self),
+                    id: id_from_def_id(def_id),
                     span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
-                    value: make_signature(&sig.decl, generics),
+                    value: make_signature(decl, generics),
                     parent: None,
                     children: vec![],
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::foreign_item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ForeignItemKind::Static(ref ty, _, _) => {
+            hir::ForeignItemKind::Static(ref ty, _) => {
                 filter!(self.span_utils, item.ident.span);
 
-                let id = id_from_node_id(item.id, self);
+                let id = id_from_def_id(def_id);
                 let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -171,28 +171,23 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::foreign_item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
             // FIXME(plietar): needs a new DefKind in rls-data
-            ast::ForeignItemKind::TyAlias(..) => None,
-            ast::ForeignItemKind::MacCall(..) => None,
+            hir::ForeignItemKind::Type => None,
         }
     }
 
-    pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
+    pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
+        let def_id = self.tcx.hir().local_def_id(item.hir_id).to_def_id();
         match item.kind {
-            ast::ItemKind::Fn(_, ref sig, .., ref generics, _) => {
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
-                );
+            hir::ItemKind::Fn(ref sig, ref generics, _) => {
+                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
                 filter!(self.span_utils, item.ident.span);
                 Some(Data::DefData(Def {
                     kind: DefKind::Function,
-                    id: id_from_node_id(item.id, self),
+                    id: id_from_def_id(def_id),
                     span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
@@ -202,20 +197,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ItemKind::Static(ref typ, ..) => {
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
-                );
+            hir::ItemKind::Static(ref typ, ..) => {
+                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
 
                 filter!(self.span_utils, item.ident.span);
 
-                let id = id_from_node_id(item.id, self);
+                let id = id_from_def_id(def_id);
                 let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -230,19 +220,14 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ItemKind::Const(_, ref typ, _) => {
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
-                );
+            hir::ItemKind::Const(ref typ, _) => {
+                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
                 filter!(self.span_utils, item.ident.span);
 
-                let id = id_from_node_id(item.id, self);
+                let id = id_from_def_id(def_id);
                 let span = self.span_from_span(item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -257,16 +242,11 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ItemKind::Mod(ref m) => {
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
-                );
+            hir::ItemKind::Mod(ref m) => {
+                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
 
                 let sm = self.tcx.sess.source_map();
                 let filename = sm.span_to_filename(m.inner);
@@ -275,48 +255,43 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
 
                 Some(Data::DefData(Def {
                     kind: DefKind::Mod,
-                    id: id_from_node_id(item.id, self),
+                    id: id_from_def_id(def_id),
                     name: item.ident.to_string(),
                     qualname,
                     span: self.span_from_span(item.ident.span),
                     value: filename.to_string(),
                     parent: None,
-                    children: m.items.iter().map(|i| id_from_node_id(i.id, self)).collect(),
+                    children: m.item_ids.iter().map(|i| id_from_hir_id(i.id, self)).collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ItemKind::Enum(ref def, _) => {
+            hir::ItemKind::Enum(ref def, _) => {
                 let name = item.ident.to_string();
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(
-                        self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()
-                    )
-                );
+                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
                 filter!(self.span_utils, item.ident.span);
                 let variants_str =
                     def.variants.iter().map(|v| v.ident.to_string()).collect::<Vec<_>>().join(", ");
                 let value = format!("{}::{{{}}}", name, variants_str);
                 Some(Data::DefData(Def {
                     kind: DefKind::Enum,
-                    id: id_from_node_id(item.id, self),
+                    id: id_from_def_id(def_id),
                     span: self.span_from_span(item.ident.span),
                     name,
                     qualname,
                     value,
                     parent: None,
-                    children: def.variants.iter().map(|v| id_from_node_id(v.id, self)).collect(),
+                    children: def.variants.iter().map(|v| id_from_hir_id(v.id, self)).collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(item.attrs.clone(), self),
+                    attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            ast::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => {
-                if let ast::TyKind::Path(None, ref path) = self_ty.kind {
+            hir::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => {
+                if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind {
                     // Common case impl for a struct or something basic.
                     if generated_code(path.span) {
                         return None;
@@ -327,7 +302,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     let impl_id = self.next_impl_id();
                     let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_def_id(self_ty.id);
+                    let type_data = self.lookup_def_id(self_ty.hir_id);
                     type_data.map(|type_data| {
                         Data::RelationData(
                             Relation {
@@ -336,7 +311,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                                 from: id_from_def_id(type_data),
                                 to: of_trait
                                     .as_ref()
-                                    .and_then(|t| self.lookup_def_id(t.ref_id))
+                                    .and_then(|t| self.lookup_def_id(t.hir_ref_id))
                                     .map(id_from_def_id)
                                     .unwrap_or_else(null_id),
                             },
@@ -351,7 +326,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                                 parent: None,
                                 children: items
                                     .iter()
-                                    .map(|i| id_from_node_id(i.id, self))
+                                    .map(|i| id_from_hir_id(i.id.hir_id, self))
                                     .collect(),
                                 docs: String::new(),
                                 sig: None,
@@ -370,126 +345,120 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         }
     }
 
-    pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<Def> {
-        if let Some(ident) = field.ident {
-            let name = ident.to_string();
-            let qualname = format!(
-                "::{}::{}",
-                self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(scope).to_def_id()),
-                ident
-            );
-            filter!(self.span_utils, ident.span);
-            let def_id = self.tcx.hir().local_def_id_from_node_id(field.id).to_def_id();
-            let typ = self.tcx.type_of(def_id).to_string();
-
-            let id = id_from_node_id(field.id, self);
-            let span = self.span_from_span(ident.span);
-
-            Some(Def {
-                kind: DefKind::Field,
-                id,
-                span,
-                name,
-                qualname,
-                value: typ,
-                parent: Some(id_from_node_id(scope, self)),
-                children: vec![],
-                decl_id: None,
-                docs: self.docs_for_attrs(&field.attrs),
-                sig: sig::field_signature(field, self),
-                attributes: lower_attributes(field.attrs.clone(), self),
-            })
-        } else {
-            None
-        }
+    pub fn get_field_data(&self, field: &hir::StructField<'_>, scope: hir::HirId) -> Option<Def> {
+        let name = field.ident.to_string();
+        let scope_def_id = self.tcx.hir().local_def_id(scope).to_def_id();
+        let qualname = format!("::{}::{}", self.tcx.def_path_str(scope_def_id), field.ident);
+        filter!(self.span_utils, field.ident.span);
+        let field_def_id = self.tcx.hir().local_def_id(field.hir_id).to_def_id();
+        let typ = self.tcx.type_of(field_def_id).to_string();
+
+        let id = id_from_def_id(field_def_id);
+        let span = self.span_from_span(field.ident.span);
+
+        Some(Def {
+            kind: DefKind::Field,
+            id,
+            span,
+            name,
+            qualname,
+            value: typ,
+            parent: Some(id_from_def_id(scope_def_id)),
+            children: vec![],
+            decl_id: None,
+            docs: self.docs_for_attrs(&field.attrs),
+            sig: sig::field_signature(field, self),
+            attributes: lower_attributes(field.attrs.to_vec(), self),
+        })
     }
 
     // FIXME would be nice to take a MethodItem here, but the ast provides both
     // trait and impl flavours, so the caller must do the disassembly.
-    pub fn get_method_data(&self, id: ast::NodeId, ident: Ident, span: Span) -> Option<Def> {
+    pub fn get_method_data(&self, hir_id: hir::HirId, ident: Ident, span: Span) -> Option<Def> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let (qualname, parent_scope, decl_id, docs, attributes) = match self
-            .tcx
-            .impl_of_method(self.tcx.hir().local_def_id_from_node_id(id).to_def_id())
-        {
-            Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
-                Some(Node::Item(item)) => match item.kind {
-                    hir::ItemKind::Impl { ref self_ty, .. } => {
-                        let hir = self.tcx.hir();
-
-                        let mut qualname = String::from("<");
-                        qualname.push_str(&rustc_hir_pretty::id_to_string(&hir, self_ty.hir_id));
-
-                        let trait_id = self.tcx.trait_id_of_impl(impl_id);
+        let def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+        let (qualname, parent_scope, decl_id, docs, attributes) =
+            match self.tcx.impl_of_method(def_id) {
+                Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
+                    Some(Node::Item(item)) => match item.kind {
+                        hir::ItemKind::Impl { ref self_ty, .. } => {
+                            let hir = self.tcx.hir();
+
+                            let mut qualname = String::from("<");
+                            qualname
+                                .push_str(&rustc_hir_pretty::id_to_string(&hir, self_ty.hir_id));
+
+                            let trait_id = self.tcx.trait_id_of_impl(impl_id);
+                            let mut docs = String::new();
+                            let mut attrs = vec![];
+                            if let Some(Node::ImplItem(item)) = hir.find(hir_id) {
+                                docs = self.docs_for_attrs(&item.attrs);
+                                attrs = item.attrs.to_vec();
+                            }
+
+                            let mut decl_id = None;
+                            if let Some(def_id) = trait_id {
+                                // A method in a trait impl.
+                                qualname.push_str(" as ");
+                                qualname.push_str(&self.tcx.def_path_str(def_id));
+
+                                decl_id = self
+                                    .tcx
+                                    .associated_items(def_id)
+                                    .filter_by_name_unhygienic(ident.name)
+                                    .next()
+                                    .map(|item| item.def_id);
+                            }
+                            qualname.push_str(">");
+
+                            (qualname, trait_id, decl_id, docs, attrs)
+                        }
+                        _ => {
+                            span_bug!(
+                                span,
+                                "Container {:?} for method {} not an impl?",
+                                impl_id,
+                                hir_id
+                            );
+                        }
+                    },
+                    r => {
+                        span_bug!(
+                            span,
+                            "Container {:?} for method {} is not a node item {:?}",
+                            impl_id,
+                            hir_id,
+                            r
+                        );
+                    }
+                },
+                None => match self.tcx.trait_of_item(def_id) {
+                    Some(def_id) => {
                         let mut docs = String::new();
                         let mut attrs = vec![];
-                        if let Some(Node::ImplItem(item)) = hir.find(hir.node_id_to_hir_id(id)) {
+
+                        if let Some(Node::TraitItem(item)) = self.tcx.hir().find(hir_id) {
                             docs = self.docs_for_attrs(&item.attrs);
                             attrs = item.attrs.to_vec();
                         }
 
-                        let mut decl_id = None;
-                        if let Some(def_id) = trait_id {
-                            // A method in a trait impl.
-                            qualname.push_str(" as ");
-                            qualname.push_str(&self.tcx.def_path_str(def_id));
-
-                            decl_id = self
-                                .tcx
-                                .associated_items(def_id)
-                                .filter_by_name_unhygienic(ident.name)
-                                .next()
-                                .map(|item| item.def_id);
-                        }
-                        qualname.push_str(">");
-
-                        (qualname, trait_id, decl_id, docs, attrs)
+                        (
+                            format!("::{}", self.tcx.def_path_str(def_id)),
+                            Some(def_id),
+                            None,
+                            docs,
+                            attrs,
+                        )
                     }
-                    _ => {
-                        span_bug!(span, "Container {:?} for method {} not an impl?", impl_id, id);
+                    None => {
+                        debug!("could not find container for method {} at {:?}", hir_id, span);
+                        // This is not necessarily a bug, if there was a compilation error,
+                        // the tables we need might not exist.
+                        return None;
                     }
                 },
-                r => {
-                    span_bug!(
-                        span,
-                        "Container {:?} for method {} is not a node item {:?}",
-                        impl_id,
-                        id,
-                        r
-                    );
-                }
-            },
-            None => match self
-                .tcx
-                .trait_of_item(self.tcx.hir().local_def_id_from_node_id(id).to_def_id())
-            {
-                Some(def_id) => {
-                    let mut docs = String::new();
-                    let mut attrs = vec![];
-                    let hir_id = self.tcx.hir().node_id_to_hir_id(id);
-
-                    if let Some(Node::TraitItem(item)) = self.tcx.hir().find(hir_id) {
-                        docs = self.docs_for_attrs(&item.attrs);
-                        attrs = item.attrs.to_vec();
-                    }
-
-                    (
-                        format!("::{}", self.tcx.def_path_str(def_id)),
-                        Some(def_id),
-                        None,
-                        docs,
-                        attrs,
-                    )
-                }
-                None => {
-                    debug!("could not find container for method {} at {:?}", id, span);
-                    // This is not necessarily a bug, if there was a compilation error,
-                    // the tables we need might not exist.
-                    return None;
-                }
-            },
-        };
+            };
 
         let qualname = format!("{}::{}", qualname, ident.name);
 
@@ -497,7 +466,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
 
         Some(Def {
             kind: DefKind::Method,
-            id: id_from_node_id(id, self),
+            id: id_from_def_id(def_id),
             span: self.span_from_span(ident.span),
             name: ident.name.to_string(),
             qualname,
@@ -512,8 +481,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         })
     }
 
-    pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
-        self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| {
+    pub fn get_trait_ref_data(&self, trait_ref: &hir::TraitRef<'_>) -> Option<Ref> {
+        self.lookup_def_id(trait_ref.hir_ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
             if generated_code(span) {
                 return None;
@@ -525,22 +494,20 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         })
     }
 
-    pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
-        let expr_hir_id = self.tcx.hir().node_id_to_hir_id(expr.id);
-        let hir_node = self.tcx.hir().expect_expr(expr_hir_id);
+    pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
+        let hir_node = self.tcx.hir().expect_expr(expr.hir_id);
         let ty = self.tables.expr_ty_adjusted_opt(&hir_node);
         if ty.is_none() || ty.unwrap().kind == ty::Error {
             return None;
         }
         match expr.kind {
-            ast::ExprKind::Field(ref sub_ex, ident) => {
-                let sub_ex_hir_id = self.tcx.hir().node_id_to_hir_id(sub_ex.id);
-                let hir_node = match self.tcx.hir().find(sub_ex_hir_id) {
+            hir::ExprKind::Field(ref sub_ex, ident) => {
+                let hir_node = match self.tcx.hir().find(sub_ex.hir_id) {
                     Some(Node::Expr(expr)) => expr,
                     _ => {
                         debug!(
                             "Missing or weird node for sub-expression {} in {:?}",
-                            sub_ex.id, expr
+                            sub_ex.hir_id, expr
                         );
                         return None;
                     }
@@ -567,7 +534,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     }
                 }
             }
-            ast::ExprKind::Struct(ref path, ..) => {
+            hir::ExprKind::Struct(hir::QPath::Resolved(_, path), ..) => {
                 match self.tables.expr_ty_adjusted(&hir_node).kind {
                     ty::Adt(def, _) if !def.is_enum() => {
                         let sub_span = path.segments.last().unwrap().ident.span;
@@ -587,9 +554,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     }
                 }
             }
-            ast::ExprKind::MethodCall(ref seg, ..) => {
-                let expr_hir_id = self.tcx.hir().definitions().node_id_to_hir_id(expr.id);
-                let method_id = match self.tables.type_dependent_def_id(expr_hir_id) {
+            hir::ExprKind::MethodCall(ref seg, ..) => {
+                let method_id = match self.tables.type_dependent_def_id(expr.hir_id) {
                     Some(id) => id,
                     None => {
                         debug!("could not resolve method id for {:?}", expr);
@@ -609,8 +575,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
                 }))
             }
-            ast::ExprKind::Path(_, ref path) => {
-                self.get_path_data(expr.id, path).map(Data::RefData)
+            hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
+                self.get_path_data(expr.hir_id, path).map(Data::RefData)
             }
             _ => {
                 // FIXME
@@ -619,12 +585,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         }
     }
 
-    pub fn get_path_res(&self, id: NodeId) -> Res {
-        // FIXME(#71104)
-        let hir_id = match self.tcx.hir().opt_node_id_to_hir_id(id) {
-            Some(id) => id,
-            None => return Res::Err,
-        };
+    pub fn get_path_res(&self, hir_id: hir::HirId) -> Res {
         match self.tcx.hir().get(hir_id) {
             Node::TraitRef(tr) => tr.path.res,
 
@@ -638,7 +599,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                 Some(res) if res != Res::Err => res,
                 _ => {
                     let parent_node = self.tcx.hir().get_parent_node(hir_id);
-                    self.get_path_res(self.tcx.hir().hir_id_to_node_id(parent_node))
+                    self.get_path_res(parent_node)
                 }
             },
 
@@ -666,33 +627,24 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         }
     }
 
-    pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
+    pub fn get_path_data(&self, id: hir::HirId, path: &hir::Path<'_>) -> Option<Ref> {
         path.segments.last().and_then(|seg| {
             self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
         })
     }
 
-    pub fn get_path_segment_data(&self, path_seg: &ast::PathSegment) -> Option<Ref> {
-        self.get_path_segment_data_with_id(path_seg, path_seg.id)
+    pub fn get_path_segment_data(&self, path_seg: &hir::PathSegment<'_>) -> Option<Ref> {
+        self.get_path_segment_data_with_id(path_seg, path_seg.hir_id?)
     }
 
-    fn get_path_segment_data_with_id(
+    pub fn get_path_segment_data_with_id(
         &self,
-        path_seg: &ast::PathSegment,
-        id: NodeId,
+        path_seg: &hir::PathSegment<'_>,
+        id: hir::HirId,
     ) -> Option<Ref> {
         // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
-        fn fn_type(seg: &ast::PathSegment) -> bool {
-            if let Some(ref generic_args) = seg.args {
-                if let ast::GenericArgs::Parenthesized(_) = **generic_args {
-                    return true;
-                }
-            }
-            false
-        }
-
-        if id == DUMMY_NODE_ID {
-            return None;
+        fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
+            seg.args.map(|args| args.parenthesized).unwrap_or(false)
         }
 
         let res = self.get_path_res(id);
@@ -701,11 +653,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         let span = self.span_from_span(span);
 
         match res {
-            Res::Local(id) => Some(Ref {
-                kind: RefKind::Variable,
-                span,
-                ref_id: id_from_node_id(self.tcx.hir().hir_id_to_node_id(id), self),
-            }),
+            Res::Local(id) => {
+                Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_hir_id(id, self) })
+            }
             Res::Def(HirDefKind::Trait, def_id) if fn_type(path_seg) => {
                 Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) })
             }
@@ -791,7 +741,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
 
     pub fn get_field_ref_data(
         &self,
-        field_ref: &ast::Field,
+        field_ref: &hir::Field<'_>,
         variant: &ty::VariantDef,
     ) -> Option<Ref> {
         filter!(self.span_utils, field_ref.ident.span);
@@ -839,14 +789,14 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         })
     }
 
-    fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
+    fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
         match self.get_path_res(ref_id) {
             Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None,
             def => def.opt_def_id(),
         }
     }
 
-    fn docs_for_attrs(&self, attrs: &[Attribute]) -> String {
+    fn docs_for_attrs(&self, attrs: &[ast::Attribute]) -> String {
         let mut result = String::new();
 
         for attr in attrs {
@@ -890,7 +840,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
     }
 }
 
-fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
+fn make_signature(decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>) -> String {
     let mut sig = "fn ".to_owned();
     if !generics.params.is_empty() {
         sig.push('<');
@@ -898,18 +848,18 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
             &generics
                 .params
                 .iter()
-                .map(|param| param.ident.to_string())
+                .map(|param| param.name.ident().to_string())
                 .collect::<Vec<_>>()
                 .join(", "),
         );
         sig.push_str("> ");
     }
     sig.push('(');
-    sig.push_str(&decl.inputs.iter().map(param_to_string).collect::<Vec<_>>().join(", "));
+    sig.push_str(&decl.inputs.iter().map(ty_to_string).collect::<Vec<_>>().join(", "));
     sig.push(')');
     match decl.output {
-        ast::FnRetTy::Default(_) => sig.push_str(" -> ()"),
-        ast::FnRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
+        hir::FnRetTy::DefaultReturn(_) => sig.push_str(" -> ()"),
+        hir::FnRetTy::Return(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
     }
 
     sig
@@ -918,26 +868,33 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
 // An AST visitor for collecting paths (e.g., the names of structs) and formal
 // variables (idents) from patterns.
 struct PathCollector<'l> {
-    collected_paths: Vec<(NodeId, &'l ast::Path)>,
-    collected_idents: Vec<(NodeId, Ident, ast::Mutability)>,
+    tcx: TyCtxt<'l>,
+    collected_paths: Vec<(hir::HirId, &'l hir::QPath<'l>)>,
+    collected_idents: Vec<(hir::HirId, Ident, hir::Mutability)>,
 }
 
 impl<'l> PathCollector<'l> {
-    fn new() -> PathCollector<'l> {
-        PathCollector { collected_paths: vec![], collected_idents: vec![] }
+    fn new(tcx: TyCtxt<'l>) -> PathCollector<'l> {
+        PathCollector { tcx, collected_paths: vec![], collected_idents: vec![] }
     }
 }
 
 impl<'l> Visitor<'l> for PathCollector<'l> {
-    fn visit_pat(&mut self, p: &'l ast::Pat) {
+    type Map = Map<'l>;
+
+    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+        intravisit::NestedVisitorMap::All(self.tcx.hir())
+    }
+
+    fn visit_pat(&mut self, p: &'l hir::Pat<'l>) {
         match p.kind {
-            PatKind::Struct(ref path, ..) => {
-                self.collected_paths.push((p.id, path));
+            hir::PatKind::Struct(ref path, ..) => {
+                self.collected_paths.push((p.hir_id, path));
             }
-            PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => {
-                self.collected_paths.push((p.id, path));
+            hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
+                self.collected_paths.push((p.hir_id, path));
             }
-            PatKind::Ident(bm, ident, _) => {
+            hir::PatKind::Binding(bm, _, ident, _) => {
                 debug!(
                     "PathCollector, visit ident in pat {}: {:?} {:?}",
                     ident, p.span, ident.span
@@ -946,14 +903,18 @@ impl<'l> Visitor<'l> for PathCollector<'l> {
                     // Even if the ref is mut, you can't change the ref, only
                     // the data pointed at, so showing the initialising expression
                     // is still worthwhile.
-                    ast::BindingMode::ByRef(_) => ast::Mutability::Not,
-                    ast::BindingMode::ByValue(mt) => mt,
+                    hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Ref => {
+                        hir::Mutability::Not
+                    }
+                    hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut => {
+                        hir::Mutability::Mut
+                    }
                 };
-                self.collected_idents.push((p.id, ident, immut));
+                self.collected_idents.push((p.hir_id, ident, immut));
             }
             _ => {}
         }
-        visit::walk_pat(self, p);
+        intravisit::walk_pat(self, p);
     }
 }
 
@@ -1035,7 +996,6 @@ impl SaveHandler for CallbackHandler<'_> {
 
 pub fn process_crate<'l, 'tcx, H: SaveHandler>(
     tcx: TyCtxt<'tcx>,
-    krate: &ast::Crate,
     cratename: &str,
     input: &'l Input,
     config: Option<Config>,
@@ -1063,9 +1023,9 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
 
         let mut visitor = DumpVisitor::new(save_ctxt);
 
-        visitor.dump_crate_info(cratename, krate);
+        visitor.dump_crate_info(cratename, tcx.hir().krate());
         visitor.dump_compilation_options(input, cratename);
-        visit::walk_crate(&mut visitor, krate);
+        visitor.process_crate(tcx.hir().krate());
 
         handler.save(&visitor.save_ctxt, &visitor.analysis())
     })
@@ -1109,13 +1069,17 @@ fn id_from_def_id(id: DefId) -> rls_data::Id {
     rls_data::Id { krate: id.krate.as_u32(), index: id.index.as_u32() }
 }
 
-fn id_from_node_id(id: NodeId, scx: &SaveContext<'_, '_>) -> rls_data::Id {
-    let def_id = scx.tcx.hir().opt_local_def_id_from_node_id(id);
+fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_, '_>) -> rls_data::Id {
+    let def_id = scx.tcx.hir().opt_local_def_id(id);
     def_id.map(|id| id_from_def_id(id.to_def_id())).unwrap_or_else(|| {
-        // Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId`
-        // out of the maximum u32 value. This will work unless you have *billions*
-        // of definitions in a single crate (very unlikely to actually happen).
-        rls_data::Id { krate: LOCAL_CRATE.as_u32(), index: !id.as_u32() }
+        // Create a *fake* `DefId` out of a `HirId` by combining the owner
+        // `local_def_index` and the `local_id`.
+        // This will work unless you have *billions* of definitions in a single
+        // crate (very unlikely to actually happen).
+        rls_data::Id {
+            krate: LOCAL_CRATE.as_u32(),
+            index: id.owner.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
+        }
     })
 }
 
@@ -1123,7 +1087,10 @@ fn null_id() -> rls_data::Id {
     rls_data::Id { krate: u32::max_value(), index: u32::max_value() }
 }
 
-fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext<'_, '_>) -> Vec<rls_data::Attribute> {
+fn lower_attributes(
+    attrs: Vec<ast::Attribute>,
+    scx: &SaveContext<'_, '_>,
+) -> Vec<rls_data::Attribute> {
     attrs
         .into_iter()
         // Only retain real attributes. Doc comments are lowered separately.
@@ -1133,7 +1100,7 @@ fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext<'_, '_>) -> Vec<rls
             // attribute. First normalize all inner attribute (#![..]) to outer
             // ones (#[..]), then remove the two leading and the one trailing character.
             attr.style = ast::AttrStyle::Outer;
-            let value = pprust::attribute_to_string(&attr);
+            let value = attribute_to_string(&attr);
             // This str slicing works correctly, because the leading and trailing characters
             // are in the ASCII range and thus exactly one byte each.
             let value = value[2..value.len() - 1].to_string();
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index bda9ff93b02..6fec5cdba8b 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -25,16 +25,18 @@
 //
 // FIXME where clauses need implementing, defs/refs in generics are mostly missing.
 
-use crate::{id_from_def_id, id_from_node_id, SaveContext};
+use crate::{id_from_def_id, id_from_hir_id, SaveContext};
 
 use rls_data::{SigElement, Signature};
 
-use rustc_ast::ast::{self, Extern, NodeId};
-use rustc_ast_pretty::pprust;
+use rustc_ast::ast::Mutability;
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir_pretty::id_to_string;
+use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
 use rustc_span::symbol::{Ident, Symbol};
 
-pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
+pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_, '_>) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
@@ -42,7 +44,7 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Sig
 }
 
 pub fn foreign_item_signature(
-    item: &ast::ForeignItem,
+    item: &hir::ForeignItem<'_>,
     scx: &SaveContext<'_, '_>,
 ) -> Option<Signature> {
     if !scx.config.signatures {
@@ -53,7 +55,10 @@ pub fn foreign_item_signature(
 
 /// Signature for a struct or tuple field declaration.
 /// Does not include a trailing comma.
-pub fn field_signature(field: &ast::StructField, scx: &SaveContext<'_, '_>) -> Option<Signature> {
+pub fn field_signature(
+    field: &hir::StructField<'_>,
+    scx: &SaveContext<'_, '_>,
+) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
@@ -61,7 +66,10 @@ pub fn field_signature(field: &ast::StructField, scx: &SaveContext<'_, '_>) -> O
 }
 
 /// Does not include a trailing comma.
-pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> Option<Signature> {
+pub fn variant_signature(
+    variant: &hir::Variant<'_>,
+    scx: &SaveContext<'_, '_>,
+) -> Option<Signature> {
     if !scx.config.signatures {
         return None;
     }
@@ -69,10 +77,10 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> O
 }
 
 pub fn method_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Ident,
-    generics: &ast::Generics,
-    m: &ast::FnSig,
+    generics: &hir::Generics<'_>,
+    m: &hir::FnSig<'_>,
     scx: &SaveContext<'_, '_>,
 ) -> Option<Signature> {
     if !scx.config.signatures {
@@ -82,10 +90,10 @@ pub fn method_signature(
 }
 
 pub fn assoc_const_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Symbol,
-    ty: &ast::Ty,
-    default: Option<&ast::Expr>,
+    ty: &hir::Ty<'_>,
+    default: Option<&hir::Expr<'_>>,
     scx: &SaveContext<'_, '_>,
 ) -> Option<Signature> {
     if !scx.config.signatures {
@@ -95,10 +103,10 @@ pub fn assoc_const_signature(
 }
 
 pub fn assoc_type_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Ident,
-    bounds: Option<&ast::GenericBounds>,
-    default: Option<&ast::Ty>,
+    bounds: Option<hir::GenericBounds<'_>>,
+    default: Option<&hir::Ty<'_>>,
     scx: &SaveContext<'_, '_>,
 ) -> Option<Signature> {
     if !scx.config.signatures {
@@ -110,7 +118,7 @@ pub fn assoc_type_signature(
 type Result = std::result::Result<Signature, &'static str>;
 
 trait Sig {
-    fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result;
+    fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_, '_>) -> Result;
 }
 
 fn extend_sig(
@@ -145,39 +153,34 @@ fn text_sig(text: String) -> Signature {
     Signature { text, defs: vec![], refs: vec![] }
 }
 
-fn push_extern(text: &mut String, ext: Extern) {
-    match ext {
-        Extern::None => {}
-        Extern::Implicit => text.push_str("extern "),
-        Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)),
-    }
-}
-
-impl Sig for ast::Ty {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
-        let id = Some(self.id);
+impl<'hir> Sig for hir::Ty<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        _parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
+        let id = Some(self.hir_id);
         match self.kind {
-            ast::TyKind::Slice(ref ty) => {
+            hir::TyKind::Slice(ref ty) => {
                 let nested = ty.make(offset + 1, id, scx)?;
                 let text = format!("[{}]", nested.text);
                 Ok(replace_text(nested, text))
             }
-            ast::TyKind::Ptr(ref mt) => {
+            hir::TyKind::Ptr(ref mt) => {
                 let prefix = match mt.mutbl {
-                    ast::Mutability::Mut => "*mut ",
-                    ast::Mutability::Not => "*const ",
+                    hir::Mutability::Mut => "*mut ",
+                    hir::Mutability::Not => "*const ",
                 };
                 let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
                 let text = format!("{}{}", prefix, nested.text);
                 Ok(replace_text(nested, text))
             }
-            ast::TyKind::Rptr(ref lifetime, ref mt) => {
+            hir::TyKind::Rptr(ref lifetime, ref mt) => {
                 let mut prefix = "&".to_owned();
-                if let &Some(ref l) = lifetime {
-                    prefix.push_str(&l.ident.to_string());
-                    prefix.push(' ');
-                }
-                if let ast::Mutability::Mut = mt.mutbl {
+                prefix.push_str(&lifetime.name.ident().to_string());
+                prefix.push(' ');
+                if let hir::Mutability::Mut = mt.mutbl {
                     prefix.push_str("mut ");
                 };
 
@@ -185,9 +188,8 @@ impl Sig for ast::Ty {
                 let text = format!("{}{}", prefix, nested.text);
                 Ok(replace_text(nested, text))
             }
-            ast::TyKind::Never => Ok(text_sig("!".to_owned())),
-            ast::TyKind::CVarArgs => Ok(text_sig("...".to_owned())),
-            ast::TyKind::Tup(ref ts) => {
+            hir::TyKind::Never => Ok(text_sig("!".to_owned())),
+            hir::TyKind::Tup(ts) => {
                 let mut text = "(".to_owned();
                 let mut defs = vec![];
                 let mut refs = vec![];
@@ -201,12 +203,7 @@ impl Sig for ast::Ty {
                 text.push(')');
                 Ok(Signature { text, defs, refs })
             }
-            ast::TyKind::Paren(ref ty) => {
-                let nested = ty.make(offset + 1, id, scx)?;
-                let text = format!("({})", nested.text);
-                Ok(replace_text(nested, text))
-            }
-            ast::TyKind::BareFn(ref f) => {
+            hir::TyKind::BareFn(ref f) => {
                 let mut text = String::new();
                 if !f.generic_params.is_empty() {
                     // FIXME defs, bounds on lifetimes
@@ -215,8 +212,8 @@ impl Sig for ast::Ty {
                         &f.generic_params
                             .iter()
                             .filter_map(|param| match param.kind {
-                                ast::GenericParamKind::Lifetime { .. } => {
-                                    Some(param.ident.to_string())
+                                hir::GenericParamKind::Lifetime { .. } => {
+                                    Some(param.name.ident().to_string())
                                 }
                                 _ => None,
                             })
@@ -226,23 +223,22 @@ impl Sig for ast::Ty {
                     text.push('>');
                 }
 
-                if let ast::Unsafe::Yes(_) = f.unsafety {
+                if let hir::Unsafety::Unsafe = f.unsafety {
                     text.push_str("unsafe ");
                 }
-                push_extern(&mut text, f.ext);
                 text.push_str("fn(");
 
                 let mut defs = vec![];
                 let mut refs = vec![];
-                for i in &f.decl.inputs {
-                    let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?;
+                for i in f.decl.inputs {
+                    let nested = i.make(offset + text.len(), Some(i.hir_id), scx)?;
                     text.push_str(&nested.text);
                     text.push(',');
                     defs.extend(nested.defs.into_iter());
                     refs.extend(nested.refs.into_iter());
                 }
                 text.push(')');
-                if let ast::FnRetTy::Ty(ref t) = f.decl.output {
+                if let hir::FnRetTy::Return(ref t) = f.decl.output {
                     text.push_str(" -> ");
                     let nested = t.make(offset + text.len(), None, scx)?;
                     text.push_str(&nested.text);
@@ -253,23 +249,19 @@ impl Sig for ast::Ty {
 
                 Ok(Signature { text, defs, refs })
             }
-            ast::TyKind::Path(None, ref path) => path.make(offset, id, scx),
-            ast::TyKind::Path(Some(ref qself), ref path) => {
-                let nested_ty = qself.ty.make(offset + 1, id, scx)?;
-                let prefix = if qself.position == 0 {
-                    format!("<{}>::", nested_ty.text)
-                } else if qself.position == 1 {
-                    let first = pprust::path_segment_to_string(&path.segments[0]);
-                    format!("<{} as {}>::", nested_ty.text, first)
-                } else {
-                    // FIXME handle path instead of elipses.
-                    format!("<{} as ...>::", nested_ty.text)
-                };
+            hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.make(offset, id, scx),
+            hir::TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref path)) => {
+                let nested_ty = qself.make(offset + 1, id, scx)?;
+                let prefix = format!(
+                    "<{} as {}>::",
+                    nested_ty.text,
+                    path_segment_to_string(&path.segments[0])
+                );
 
-                let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?);
+                let name = path_segment_to_string(path.segments.last().ok_or("Bad path")?);
                 let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
                 let id = id_from_def_id(res.def_id());
-                if path.segments.len() - qself.position == 1 {
+                if path.segments.len() == 2 {
                     let start = offset + prefix.len();
                     let end = start + name.len();
 
@@ -289,44 +281,60 @@ impl Sig for ast::Ty {
                     })
                 }
             }
-            ast::TyKind::TraitObject(ref bounds, ..) => {
+            hir::TyKind::TraitObject(bounds, ..) => {
                 // FIXME recurse into bounds
-                let nested = pprust::bounds_to_string(bounds);
+                let bounds: Vec<hir::GenericBound<'_>> = bounds
+                    .iter()
+                    .map(|hir::PolyTraitRef { bound_generic_params, trait_ref, span }| {
+                        hir::GenericBound::Trait(
+                            hir::PolyTraitRef {
+                                bound_generic_params,
+                                trait_ref: hir::TraitRef {
+                                    path: trait_ref.path,
+                                    hir_ref_id: trait_ref.hir_ref_id,
+                                },
+                                span: *span,
+                            },
+                            hir::TraitBoundModifier::None,
+                        )
+                    })
+                    .collect();
+                let nested = bounds_to_string(&bounds);
                 Ok(text_sig(nested))
             }
-            ast::TyKind::ImplTrait(_, ref bounds) => {
-                // FIXME recurse into bounds
-                let nested = pprust::bounds_to_string(bounds);
-                Ok(text_sig(format!("impl {}", nested)))
-            }
-            ast::TyKind::Array(ref ty, ref v) => {
+            hir::TyKind::Array(ref ty, ref anon_const) => {
                 let nested_ty = ty.make(offset + 1, id, scx)?;
-                let expr = pprust::expr_to_string(&v.value).replace('\n', " ");
+                let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " ");
                 let text = format!("[{}; {}]", nested_ty.text, expr);
                 Ok(replace_text(nested_ty, text))
             }
-            ast::TyKind::Typeof(_)
-            | ast::TyKind::Infer
-            | ast::TyKind::Err
-            | ast::TyKind::ImplicitSelf
-            | ast::TyKind::MacCall(_) => Err("Ty"),
+            hir::TyKind::Typeof(_)
+            | hir::TyKind::Infer
+            | hir::TyKind::Def(..)
+            | hir::TyKind::Path(..)
+            | hir::TyKind::Err => Err("Ty"),
         }
     }
 }
 
-impl Sig for ast::Item {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
-        let id = Some(self.id);
+impl<'hir> Sig for hir::Item<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        _parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
+        let id = Some(self.hir_id);
 
         match self.kind {
-            ast::ItemKind::Static(ref ty, m, ref expr) => {
+            hir::ItemKind::Static(ref ty, m, ref body) => {
                 let mut text = "static ".to_owned();
-                if m == ast::Mutability::Mut {
+                if m == hir::Mutability::Mut {
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
+                    id: id_from_hir_id(self.hir_id, scx),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -336,21 +344,19 @@ impl Sig for ast::Item {
                 let ty = ty.make(offset + text.len(), id, scx)?;
                 text.push_str(&ty.text);
 
-                if let Some(expr) = expr {
-                    text.push_str(" = ");
-                    let expr = pprust::expr_to_string(expr).replace('\n', " ");
-                    text.push_str(&expr);
-                }
+                text.push_str(" = ");
+                let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
+                text.push_str(&expr);
 
                 text.push(';');
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Const(_, ref ty, ref expr) => {
+            hir::ItemKind::Const(ref ty, ref body) => {
                 let mut text = "const ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
+                    id: id_from_hir_id(self.hir_id, scx),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -360,38 +366,35 @@ impl Sig for ast::Item {
                 let ty = ty.make(offset + text.len(), id, scx)?;
                 text.push_str(&ty.text);
 
-                if let Some(expr) = expr {
-                    text.push_str(" = ");
-                    let expr = pprust::expr_to_string(expr).replace('\n', " ");
-                    text.push_str(&expr);
-                }
+                text.push_str(" = ");
+                let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
+                text.push_str(&expr);
 
                 text.push(';');
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Fn(_, ast::FnSig { ref decl, header }, ref generics, _) => {
+            hir::ItemKind::Fn(hir::FnSig { ref decl, header }, ref generics, _) => {
                 let mut text = String::new();
-                if let ast::Const::Yes(_) = header.constness {
+                if let hir::Constness::Const = header.constness {
                     text.push_str("const ");
                 }
-                if header.asyncness.is_async() {
+                if hir::IsAsync::Async == header.asyncness {
                     text.push_str("async ");
                 }
-                if let ast::Unsafe::Yes(_) = header.unsafety {
+                if let hir::Unsafety::Unsafe = header.unsafety {
                     text.push_str("unsafe ");
                 }
-                push_extern(&mut text, header.ext);
                 text.push_str("fn ");
 
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
 
                 sig.text.push('(');
-                for i in &decl.inputs {
+                for i in decl.inputs {
                     // FIXME should descend into patterns to add defs.
-                    sig.text.push_str(&pprust::pat_to_string(&i.pat));
                     sig.text.push_str(": ");
-                    let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
+                    let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
                     sig.text.push_str(&nested.text);
                     sig.text.push(',');
                     sig.defs.extend(nested.defs.into_iter());
@@ -399,7 +402,7 @@ impl Sig for ast::Item {
                 }
                 sig.text.push(')');
 
-                if let ast::FnRetTy::Ty(ref t) = decl.output {
+                if let hir::FnRetTy::Return(ref t) = decl.output {
                     sig.text.push_str(" -> ");
                     let nested = t.make(offset + sig.text.len(), None, scx)?;
                     sig.text.push_str(&nested.text);
@@ -410,11 +413,11 @@ impl Sig for ast::Item {
 
                 Ok(sig)
             }
-            ast::ItemKind::Mod(ref _mod) => {
+            hir::ItemKind::Mod(ref _mod) => {
                 let mut text = "mod ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
+                    id: id_from_hir_id(self.hir_id, scx),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -424,78 +427,82 @@ impl Sig for ast::Item {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ItemKind::TyAlias(_, ref generics, _, ref ty) => {
+            hir::ItemKind::TyAlias(ref ty, ref generics) => {
                 let text = "type ".to_owned();
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
 
                 sig.text.push_str(" = ");
-                let ty = match ty {
-                    Some(ty) => ty.make(offset + sig.text.len(), id, scx)?,
-                    None => return Err("Ty"),
-                };
+                let ty = ty.make(offset + sig.text.len(), id, scx)?;
                 sig.text.push_str(&ty.text);
                 sig.text.push(';');
 
                 Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
             }
-            ast::ItemKind::Enum(_, ref generics) => {
+            hir::ItemKind::Enum(_, ref generics) => {
                 let text = "enum ".to_owned();
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
-            ast::ItemKind::Struct(_, ref generics) => {
+            hir::ItemKind::Struct(_, ref generics) => {
                 let text = "struct ".to_owned();
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
-            ast::ItemKind::Union(_, ref generics) => {
+            hir::ItemKind::Union(_, ref generics) => {
                 let text = "union ".to_owned();
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
-            ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
+            hir::ItemKind::Trait(is_auto, unsafety, ref generics, bounds, _) => {
                 let mut text = String::new();
 
-                if is_auto == ast::IsAuto::Yes {
+                if is_auto == hir::IsAuto::Yes {
                     text.push_str("auto ");
                 }
 
-                if let ast::Unsafe::Yes(_) = unsafety {
+                if let hir::Unsafety::Unsafe = unsafety {
                     text.push_str("unsafe ");
                 }
                 text.push_str("trait ");
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
 
                 if !bounds.is_empty() {
                     sig.text.push_str(": ");
-                    sig.text.push_str(&pprust::bounds_to_string(bounds));
+                    sig.text.push_str(&bounds_to_string(bounds));
                 }
                 // FIXME where clause
                 sig.text.push_str(" {}");
 
                 Ok(sig)
             }
-            ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
+            hir::ItemKind::TraitAlias(ref generics, bounds) => {
                 let mut text = String::new();
                 text.push_str("trait ");
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
 
                 if !bounds.is_empty() {
                     sig.text.push_str(" = ");
-                    sig.text.push_str(&pprust::bounds_to_string(bounds));
+                    sig.text.push_str(&bounds_to_string(bounds));
                 }
                 // FIXME where clause
                 sig.text.push_str(";");
 
                 Ok(sig)
             }
-            ast::ItemKind::Impl {
+            hir::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
+                defaultness_span: _,
                 constness,
                 ref generics,
                 ref of_trait,
@@ -503,14 +510,14 @@ impl Sig for ast::Item {
                 items: _,
             } => {
                 let mut text = String::new();
-                if let ast::Defaultness::Default(_) = defaultness {
+                if let hir::Defaultness::Default { .. } = defaultness {
                     text.push_str("default ");
                 }
-                if let ast::Unsafe::Yes(_) = unsafety {
+                if let hir::Unsafety::Unsafe = unsafety {
                     text.push_str("unsafe ");
                 }
                 text.push_str("impl");
-                if let ast::Const::Yes(_) = constness {
+                if let hir::Constness::Const = constness {
                     text.push_str(" const");
                 }
 
@@ -520,7 +527,7 @@ impl Sig for ast::Item {
                 text.push(' ');
 
                 let trait_sig = if let Some(ref t) = *of_trait {
-                    if let ast::ImplPolarity::Negative(_) = polarity {
+                    if let hir::ImplPolarity::Negative(_) = polarity {
                         text.push('!');
                     }
                     let trait_sig = t.path.make(offset + text.len(), id, scx)?;
@@ -540,27 +547,23 @@ impl Sig for ast::Item {
 
                 // FIXME where clause
             }
-            ast::ItemKind::ForeignMod(_) => Err("extern mod"),
-            ast::ItemKind::GlobalAsm(_) => Err("glboal asm"),
-            ast::ItemKind::ExternCrate(_) => Err("extern crate"),
+            hir::ItemKind::ForeignMod(_) => Err("extern mod"),
+            hir::ItemKind::GlobalAsm(_) => Err("glboal asm"),
+            hir::ItemKind::ExternCrate(_) => Err("extern crate"),
+            hir::ItemKind::OpaqueTy(..) => Err("opaque type"),
             // FIXME should implement this (e.g., pub use).
-            ast::ItemKind::Use(_) => Err("import"),
-            ast::ItemKind::MacCall(..) | ast::ItemKind::MacroDef(_) => Err("Macro"),
+            hir::ItemKind::Use(..) => Err("import"),
         }
     }
 }
 
-impl Sig for ast::Path {
-    fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+impl<'hir> Sig for hir::Path<'hir> {
+    fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_, '_>) -> Result {
         let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
 
         let (name, start, end) = match res {
             Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => {
-                return Ok(Signature {
-                    text: pprust::path_to_string(self),
-                    defs: vec![],
-                    refs: vec![],
-                });
+                return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
             }
             Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
                 let len = self.segments.len();
@@ -570,13 +573,13 @@ impl Sig for ast::Path {
                 // FIXME: really we should descend into the generics here and add SigElements for
                 // them.
                 // FIXME: would be nice to have a def for the first path segment.
-                let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]);
-                let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]);
+                let seg1 = path_segment_to_string(&self.segments[len - 2]);
+                let seg2 = path_segment_to_string(&self.segments[len - 1]);
                 let start = offset + seg1.len() + 2;
                 (format!("{}::{}", seg1, seg2), start, start + seg2.len())
             }
             _ => {
-                let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?);
+                let name = path_segment_to_string(self.segments.last().ok_or("Bad path")?);
                 let end = offset + name.len();
                 (name, offset, end)
             }
@@ -588,8 +591,13 @@ impl Sig for ast::Path {
 }
 
 // This does not cover the where clause, which must be processed separately.
-impl Sig for ast::Generics {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+impl<'hir> Sig for hir::Generics<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        _parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
         if self.params.is_empty() {
             return Ok(text_sig(String::new()));
         }
@@ -597,30 +605,30 @@ impl Sig for ast::Generics {
         let mut text = "<".to_owned();
 
         let mut defs = Vec::with_capacity(self.params.len());
-        for param in &self.params {
+        for param in self.params {
             let mut param_text = String::new();
-            if let ast::GenericParamKind::Const { .. } = param.kind {
+            if let hir::GenericParamKind::Const { .. } = param.kind {
                 param_text.push_str("const ");
             }
-            param_text.push_str(&param.ident.as_str());
+            param_text.push_str(&param.name.ident().as_str());
             defs.push(SigElement {
-                id: id_from_node_id(param.id, scx),
+                id: id_from_hir_id(param.hir_id, scx),
                 start: offset + text.len(),
                 end: offset + text.len() + param_text.as_str().len(),
             });
-            if let ast::GenericParamKind::Const { ref ty } = param.kind {
+            if let hir::GenericParamKind::Const { ref ty } = param.kind {
                 param_text.push_str(": ");
-                param_text.push_str(&pprust::ty_to_string(&ty));
+                param_text.push_str(&ty_to_string(&ty));
             }
             if !param.bounds.is_empty() {
                 param_text.push_str(": ");
                 match param.kind {
-                    ast::GenericParamKind::Lifetime { .. } => {
+                    hir::GenericParamKind::Lifetime { .. } => {
                         let bounds = param
                             .bounds
                             .iter()
                             .map(|bound| match bound {
-                                ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
+                                hir::GenericBound::Outlives(lt) => lt.name.ident().to_string(),
                                 _ => panic!(),
                             })
                             .collect::<Vec<_>>()
@@ -628,11 +636,11 @@ impl Sig for ast::Generics {
                         param_text.push_str(&bounds);
                         // FIXME add lifetime bounds refs.
                     }
-                    ast::GenericParamKind::Type { .. } => {
-                        param_text.push_str(&pprust::bounds_to_string(&param.bounds));
+                    hir::GenericParamKind::Type { .. } => {
+                        param_text.push_str(&bounds_to_string(param.bounds));
                         // FIXME descend properly into bounds.
                     }
-                    ast::GenericParamKind::Const { .. } => {
+                    hir::GenericParamKind::Const { .. } => {
                         // Const generics cannot contain bounds.
                     }
                 }
@@ -646,21 +654,24 @@ impl Sig for ast::Generics {
     }
 }
 
-impl Sig for ast::StructField {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+impl<'hir> Sig for hir::StructField<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        _parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
         let mut text = String::new();
-        let mut defs = None;
-        if let Some(ident) = self.ident {
-            text.push_str(&ident.to_string());
-            defs = Some(SigElement {
-                id: id_from_node_id(self.id, scx),
-                start: offset,
-                end: offset + text.len(),
-            });
-            text.push_str(": ");
-        }
 
-        let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?;
+        text.push_str(&self.ident.to_string());
+        let defs = Some(SigElement {
+            id: id_from_hir_id(self.hir_id, scx),
+            start: offset,
+            end: offset + text.len(),
+        });
+        text.push_str(": ");
+
+        let mut ty_sig = self.ty.make(offset + text.len(), Some(self.hir_id), scx)?;
         text.push_str(&ty_sig.text);
         ty_sig.text = text;
         ty_sig.defs.extend(defs.into_iter());
@@ -668,14 +679,19 @@ impl Sig for ast::StructField {
     }
 }
 
-impl Sig for ast::Variant {
-    fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+impl<'hir> Sig for hir::Variant<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
         let mut text = self.ident.to_string();
         match self.data {
-            ast::VariantData::Struct(ref fields, r) => {
+            hir::VariantData::Struct(fields, r) => {
                 let id = parent_id.unwrap();
                 let name_def = SigElement {
-                    id: id_from_node_id(id, scx),
+                    id: id_from_hir_id(id, scx),
                     start: offset,
                     end: offset + text.len(),
                 };
@@ -696,9 +712,9 @@ impl Sig for ast::Variant {
                 text.push('}');
                 Ok(Signature { text, defs, refs })
             }
-            ast::VariantData::Tuple(ref fields, id) => {
+            hir::VariantData::Tuple(fields, id) => {
                 let name_def = SigElement {
-                    id: id_from_node_id(id, scx),
+                    id: id_from_hir_id(id, scx),
                     start: offset,
                     end: offset + text.len(),
                 };
@@ -715,9 +731,9 @@ impl Sig for ast::Variant {
                 text.push(')');
                 Ok(Signature { text, defs, refs })
             }
-            ast::VariantData::Unit(id) => {
+            hir::VariantData::Unit(id) => {
                 let name_def = SigElement {
-                    id: id_from_node_id(id, scx),
+                    id: id_from_hir_id(id, scx),
                     start: offset,
                     end: offset + text.len(),
                 };
@@ -727,23 +743,26 @@ impl Sig for ast::Variant {
     }
 }
 
-impl Sig for ast::ForeignItem {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
-        let id = Some(self.id);
+impl<'hir> Sig for hir::ForeignItem<'hir> {
+    fn make(
+        &self,
+        offset: usize,
+        _parent_id: Option<hir::HirId>,
+        scx: &SaveContext<'_, '_>,
+    ) -> Result {
+        let id = Some(self.hir_id);
         match self.kind {
-            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
-                let decl = &sig.decl;
+            hir::ForeignItemKind::Fn(decl, _, ref generics) => {
                 let mut text = String::new();
                 text.push_str("fn ");
 
-                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+                let mut sig =
+                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
 
                 sig.text.push('(');
-                for i in &decl.inputs {
-                    // FIXME should descend into patterns to add defs.
-                    sig.text.push_str(&pprust::pat_to_string(&i.pat));
+                for i in decl.inputs {
                     sig.text.push_str(": ");
-                    let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?;
+                    let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
                     sig.text.push_str(&nested.text);
                     sig.text.push(',');
                     sig.defs.extend(nested.defs.into_iter());
@@ -751,7 +770,7 @@ impl Sig for ast::ForeignItem {
                 }
                 sig.text.push(')');
 
-                if let ast::FnRetTy::Ty(ref t) = decl.output {
+                if let hir::FnRetTy::Return(ref t) = decl.output {
                     sig.text.push_str(" -> ");
                     let nested = t.make(offset + sig.text.len(), None, scx)?;
                     sig.text.push_str(&nested.text);
@@ -762,14 +781,14 @@ impl Sig for ast::ForeignItem {
 
                 Ok(sig)
             }
-            ast::ForeignItemKind::Static(ref ty, m, _) => {
+            hir::ForeignItemKind::Static(ref ty, m) => {
                 let mut text = "static ".to_owned();
-                if m == ast::Mutability::Mut {
+                if m == Mutability::Mut {
                     text.push_str("mut ");
                 }
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
+                    id: id_from_hir_id(self.hir_id, scx),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -781,11 +800,11 @@ impl Sig for ast::ForeignItem {
 
                 Ok(extend_sig(ty_sig, text, defs, vec![]))
             }
-            ast::ForeignItemKind::TyAlias(..) => {
+            hir::ForeignItemKind::Type => {
                 let mut text = "type ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_node_id(self.id, scx),
+                    id: id_from_hir_id(self.hir_id, scx),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -794,7 +813,6 @@ impl Sig for ast::ForeignItem {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ForeignItemKind::MacCall(..) => Err("macro"),
         }
     }
 }
@@ -802,14 +820,14 @@ impl Sig for ast::ForeignItem {
 fn name_and_generics(
     mut text: String,
     offset: usize,
-    generics: &ast::Generics,
-    id: NodeId,
+    generics: &hir::Generics<'_>,
+    id: hir::HirId,
     name: Ident,
     scx: &SaveContext<'_, '_>,
 ) -> Result {
     let name = name.to_string();
     let def = SigElement {
-        id: id_from_node_id(id, scx),
+        id: id_from_hir_id(id, scx),
         start: offset + text.len(),
         end: offset + text.len() + name.len(),
     };
@@ -821,16 +839,16 @@ fn name_and_generics(
 }
 
 fn make_assoc_type_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Ident,
-    bounds: Option<&ast::GenericBounds>,
-    default: Option<&ast::Ty>,
+    bounds: Option<hir::GenericBounds<'_>>,
+    default: Option<&hir::Ty<'_>>,
     scx: &SaveContext<'_, '_>,
 ) -> Result {
     let mut text = "type ".to_owned();
     let name = ident.to_string();
     let mut defs = vec![SigElement {
-        id: id_from_node_id(id, scx),
+        id: id_from_hir_id(id, scx),
         start: text.len(),
         end: text.len() + name.len(),
     }];
@@ -839,7 +857,7 @@ fn make_assoc_type_signature(
     if let Some(bounds) = bounds {
         text.push_str(": ");
         // FIXME should descend into bounds
-        text.push_str(&pprust::bounds_to_string(bounds));
+        text.push_str(&bounds_to_string(bounds));
     }
     if let Some(default) = default {
         text.push_str(" = ");
@@ -853,16 +871,16 @@ fn make_assoc_type_signature(
 }
 
 fn make_assoc_const_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Symbol,
-    ty: &ast::Ty,
-    default: Option<&ast::Expr>,
+    ty: &hir::Ty<'_>,
+    default: Option<&hir::Expr<'_>>,
     scx: &SaveContext<'_, '_>,
 ) -> Result {
     let mut text = "const ".to_owned();
     let name = ident.to_string();
     let mut defs = vec![SigElement {
-        id: id_from_node_id(id, scx),
+        id: id_from_hir_id(id, scx),
         start: text.len(),
         end: text.len() + name.len(),
     }];
@@ -877,41 +895,38 @@ fn make_assoc_const_signature(
 
     if let Some(default) = default {
         text.push_str(" = ");
-        text.push_str(&pprust::expr_to_string(default));
+        text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
     }
     text.push(';');
     Ok(Signature { text, defs, refs })
 }
 
 fn make_method_signature(
-    id: NodeId,
+    id: hir::HirId,
     ident: Ident,
-    generics: &ast::Generics,
-    m: &ast::FnSig,
+    generics: &hir::Generics<'_>,
+    m: &hir::FnSig<'_>,
     scx: &SaveContext<'_, '_>,
 ) -> Result {
     // FIXME code dup with function signature
     let mut text = String::new();
-    if let ast::Const::Yes(_) = m.header.constness {
+    if let hir::Constness::Const = m.header.constness {
         text.push_str("const ");
     }
-    if m.header.asyncness.is_async() {
+    if hir::IsAsync::Async == m.header.asyncness {
         text.push_str("async ");
     }
-    if let ast::Unsafe::Yes(_) = m.header.unsafety {
+    if let hir::Unsafety::Unsafe = m.header.unsafety {
         text.push_str("unsafe ");
     }
-    push_extern(&mut text, m.header.ext);
     text.push_str("fn ");
 
     let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
 
     sig.text.push('(');
-    for i in &m.decl.inputs {
-        // FIXME should descend into patterns to add defs.
-        sig.text.push_str(&pprust::pat_to_string(&i.pat));
+    for i in m.decl.inputs {
         sig.text.push_str(": ");
-        let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?;
+        let nested = i.make(sig.text.len(), Some(i.hir_id), scx)?;
         sig.text.push_str(&nested.text);
         sig.text.push(',');
         sig.defs.extend(nested.defs.into_iter());
@@ -919,7 +934,7 @@ fn make_method_signature(
     }
     sig.text.push(')');
 
-    if let ast::FnRetTy::Ty(ref t) = m.decl.output {
+    if let hir::FnRetTy::Return(ref t) = m.decl.output {
         sig.text.push_str(" -> ");
         let nested = t.make(sig.text.len(), None, scx)?;
         sig.text.push_str(&nested.text);
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 085f24b9ecbc0e90d204cab1c111c4abe4608ce
+Subproject 8d7a7167c15b9154755588c39b22b2336c89ca6