about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs61
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs49
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs30
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs4
-rw-r--r--compiler/rustc_driver/src/pretty.rs24
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0543.md35
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0545.md35
-rw-r--r--compiler/rustc_expand/src/expand.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs144
-rw-r--r--compiler/rustc_hir/src/hir_id.rs15
-rw-r--r--compiler/rustc_hir/src/intravisit.rs56
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs73
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs16
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs6
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs28
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs232
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs22
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs19
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs90
-rw-r--r--compiler/rustc_lint/src/late.rs20
-rw-r--r--compiler/rustc_lint/src/levels.rs10
-rw-r--r--compiler/rustc_lint/src/traits.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs44
-rw-r--r--compiler/rustc_metadata/src/foreign_modules.rs15
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs43
-rw-r--r--compiler/rustc_middle/src/hir/map/blocks.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/collector.rs81
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs85
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ich/impls_hir.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs28
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs17
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/error.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs2
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs9
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs13
-rw-r--r--compiler/rustc_mir/src/const_eval/error.rs6
-rw-r--r--compiler/rustc_mir/src/const_eval/eval_queries.rs2
-rw-r--r--compiler/rustc_mir/src/const_eval/machine.rs4
-rw-r--r--compiler/rustc_mir/src/interpret/intern.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/validity.rs32
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs33
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/default.rs9
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs8
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs1
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs4
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs183
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs18
-rw-r--r--compiler/rustc_passes/src/dead.rs48
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs15
-rw-r--r--compiler/rustc_passes/src/entry.rs11
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs17
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs12
-rw-r--r--compiler/rustc_passes/src/lang_items.rs6
-rw-r--r--compiler/rustc_passes/src/layout_test.rs6
-rw-r--r--compiler/rustc_passes/src/reachable.rs27
-rw-r--r--compiler/rustc_passes/src/stability.rs36
-rw-r--r--compiler/rustc_plugin_impl/src/build.rs10
-rw-r--r--compiler/rustc_privacy/src/lib.rs120
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs1
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs40
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs144
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs14
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs34
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_span/src/def_id.rs4
-rw-r--r--compiler/rustc_span/src/source_map.rs42
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs12
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs19
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs19
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs23
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs2
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs65
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs6
-rw-r--r--compiler/rustc_typeck/src/check/check.rs119
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs12
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs16
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs17
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs105
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs69
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs39
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs3
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs54
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs3
-rw-r--r--compiler/rustc_typeck/src/coherence/mod.rs3
-rw-r--r--compiler/rustc_typeck/src/coherence/orphan.rs7
-rw-r--r--compiler/rustc_typeck/src/coherence/unsafety.rs3
-rw-r--r--compiler/rustc_typeck/src/collect.rs69
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs13
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check.rs9
-rw-r--r--compiler/rustc_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_typeck/src/outlives/implicit_infer.rs9
-rw-r--r--compiler/rustc_typeck/src/outlives/test.rs6
-rw-r--r--compiler/rustc_typeck/src/variance/constraints.rs12
-rw-r--r--compiler/rustc_typeck/src/variance/terms.rs14
-rw-r--r--compiler/rustc_typeck/src/variance/test.rs6
122 files changed, 1657 insertions, 1405 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 1efe83cacea..cad2a21d1a4 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -35,10 +35,10 @@ impl ItemLowerer<'_, '_, '_> {
 
 impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     fn visit_mod(&mut self, m: &'a Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
-        let hir_id = self.lctx.lower_node_id(n);
+        let def_id = self.lctx.lower_node_id(n).expect_owner();
 
         self.lctx.modules.insert(
-            hir_id,
+            def_id,
             hir::ModuleItems {
                 items: BTreeSet::new(),
                 trait_items: BTreeSet::new(),
@@ -48,7 +48,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
         );
 
         let old = self.lctx.current_module;
-        self.lctx.current_module = hir_id;
+        self.lctx.current_module = def_id;
         visit::walk_mod(self, m);
         self.lctx.current_module = old;
     }
@@ -58,8 +58,8 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             lctx.without_in_scope_lifetime_defs(|lctx| {
                 if let Some(hir_item) = lctx.lower_item(item) {
-                    item_hir_id = Some(hir_item.hir_id);
-                    lctx.insert_item(hir_item);
+                    let id = lctx.insert_item(hir_item);
+                    item_hir_id = Some(id);
                 }
             })
         });
@@ -92,13 +92,13 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
         self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
             AssocCtxt::Trait => {
                 let hir_item = lctx.lower_trait_item(item);
-                let id = hir::TraitItemId { hir_id: hir_item.hir_id };
+                let id = hir_item.trait_item_id();
                 lctx.trait_items.insert(id, hir_item);
                 lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
             }
             AssocCtxt::Impl => {
                 let hir_item = lctx.lower_impl_item(item);
-                let id = hir::ImplItemId { hir_id: hir_item.hir_id };
+                let id = hir_item.impl_item_id();
                 lctx.impl_items.insert(id, hir_item);
                 lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
             }
@@ -111,7 +111,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
         self.lctx.allocate_hir_id_counter(item.id);
         self.lctx.with_hir_id_owner(item.id, |lctx| {
             let hir_item = lctx.lower_foreign_item(item);
-            let id = hir::ForeignItemId { hir_id: hir_item.hir_id };
+            let id = hir_item.foreign_item_id();
             lctx.foreign_items.insert(id, hir_item);
             lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id);
         });
@@ -128,14 +128,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
     // only used when lowering a child item of a trait or impl.
     fn with_parent_item_lifetime_defs<T>(
         &mut self,
-        parent_hir_id: hir::HirId,
+        parent_hir_id: hir::ItemId,
         f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
 
         let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind {
             hir::ItemKind::Impl(hir::Impl { ref generics, .. })
-            | hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..],
+            | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
             _ => &[],
         };
         let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
@@ -197,7 +197,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         node_ids
             .into_iter()
-            .map(|node_id| hir::ItemId { id: self.allocate_hir_id_counter(node_id) })
+            .map(|node_id| hir::ItemId {
+                def_id: self.allocate_hir_id_counter(node_id).expect_owner(),
+            })
             .collect()
     }
 
@@ -232,13 +234,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
             if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) {
-                let hir_id = self.lower_node_id(i.id);
+                let def_id = self.lower_node_id(i.id).expect_owner();
                 let body = P(self.lower_mac_args(body));
                 self.exported_macros.push(hir::MacroDef {
                     ident,
                     vis,
                     attrs,
-                    hir_id,
+                    def_id,
                     span: i.span,
                     ast: MacroDef { body, macro_rules },
                 });
@@ -250,7 +252,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let kind = self.lower_item_kind(i.span, i.id, &mut ident, attrs, &mut vis, &i.kind);
 
-        Some(hir::Item { hir_id: self.lower_node_id(i.id), ident, attrs, kind, vis, span: i.span })
+        Some(hir::Item {
+            def_id: self.lower_node_id(i.id).expect_owner(),
+            ident,
+            attrs,
+            kind,
+            vis,
+            span: i.span,
+        })
     }
 
     fn lower_item_kind(
@@ -387,8 +396,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self_ty: ref ty,
                 items: ref impl_items,
             }) => {
-                let def_id = self.resolver.local_def_id(id);
-
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
                 //
@@ -402,10 +409,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // method, it will not be considered an in-band
                 // lifetime to be added, but rather a reference to a
                 // parent lifetime.
-                let lowered_trait_impl_id = self.lower_node_id(id);
+                let lowered_trait_def_id = self.lower_node_id(id).expect_owner();
                 let (generics, (trait_ref, lowered_ty)) = self.add_in_band_defs(
                     ast_generics,
-                    def_id,
+                    lowered_trait_def_id,
                     AnonymousLifetimeMode::CreateParameter,
                     |this, _| {
                         let trait_ref = trait_ref.as_ref().map(|trait_ref| {
@@ -417,7 +424,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                 this.trait_impls
                                     .entry(def_id)
                                     .or_default()
-                                    .push(lowered_trait_impl_id);
+                                    .push(lowered_trait_def_id);
                             }
                         }
 
@@ -557,7 +564,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         let vis = this.rebuild_vis(&vis);
 
                         this.insert_item(hir::Item {
-                            hir_id: new_id,
+                            def_id: new_id.expect_owner(),
                             ident,
                             attrs,
                             kind,
@@ -629,7 +636,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
 
                         this.insert_item(hir::Item {
-                            hir_id: new_hir_id,
+                            def_id: new_hir_id.expect_owner(),
                             ident,
                             attrs,
                             kind,
@@ -702,7 +709,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
         let def_id = self.resolver.local_def_id(i.id);
         hir::ForeignItem {
-            hir_id: self.lower_node_id(i.id),
+            def_id,
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
             kind: match i.kind {
@@ -737,7 +744,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
         hir::ForeignItemRef {
-            id: hir::ForeignItemId { hir_id: self.lower_node_id(i.id) },
+            id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() },
             ident: i.ident,
             span: i.span,
             vis: self.lower_visibility(&i.vis, Some(i.id)),
@@ -837,7 +844,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
 
         hir::TraitItem {
-            hir_id: self.lower_node_id(i.id),
+            def_id: trait_item_def_id,
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
             generics,
@@ -857,7 +864,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
-        let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) };
+        let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() };
         let defaultness = hir::Defaultness::Default { has_value: has_default };
         hir::TraitItemRef { id, ident: i.ident, span: i.span, defaultness, kind }
     }
@@ -922,7 +929,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         hir::ImplItem {
-            hir_id: self.lower_node_id(i.id),
+            def_id: self.lower_node_id(i.id).expect_owner(),
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
             generics,
@@ -938,7 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         hir::ImplItemRef {
-            id: hir::ImplItemId { hir_id: self.lower_node_id(i.id) },
+            id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() },
             ident: i.ident,
             span: i.span,
             vis: self.lower_visibility(&i.vis, Some(i.id)),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index f076dca5cf5..9d0b2cd5c67 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -48,7 +48,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
@@ -99,7 +99,7 @@ struct LoweringContext<'a, 'hir: 'a> {
     arena: &'hir Arena<'hir>,
 
     /// The items being lowered are collected here.
-    items: BTreeMap<hir::HirId, hir::Item<'hir>>,
+    items: BTreeMap<hir::ItemId, hir::Item<'hir>>,
 
     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
@@ -108,9 +108,9 @@ struct LoweringContext<'a, 'hir: 'a> {
     exported_macros: Vec<hir::MacroDef<'hir>>,
     non_exported_macro_attrs: Vec<ast::Attribute>,
 
-    trait_impls: BTreeMap<DefId, Vec<hir::HirId>>,
+    trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
 
-    modules: BTreeMap<hir::HirId, hir::ModuleItems>,
+    modules: BTreeMap<LocalDefId, hir::ModuleItems>,
 
     generator_kind: Option<hir::GeneratorKind>,
 
@@ -158,7 +158,7 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// vector.
     in_scope_lifetimes: Vec<ParamName>,
 
-    current_module: hir::HirId,
+    current_module: LocalDefId,
 
     type_def_lifetime_params: DefIdMap<usize>,
 
@@ -314,8 +314,8 @@ pub fn lower_crate<'a, 'hir>(
         is_in_dyn_type: false,
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
         type_def_lifetime_params: Default::default(),
-        current_module: hir::CRATE_HIR_ID,
-        current_hir_id_owner: vec![(LocalDefId { local_def_index: CRATE_DEF_INDEX }, 0)],
+        current_module: CRATE_DEF_ID,
+        current_hir_id_owner: vec![(CRATE_DEF_ID, 0)],
         item_local_id_counters: Default::default(),
         node_id_to_hir_id: IndexVec::new(),
         generator_kind: None,
@@ -605,12 +605,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn insert_item(&mut self, item: hir::Item<'hir>) {
-        let id = item.hir_id;
-        // FIXME: Use `debug_asset-rt`.
-        assert_eq!(id.local_id, hir::ItemLocalId::from_u32(0));
+    fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
+        let id = hir::ItemId { def_id: item.def_id };
         self.items.insert(id, item);
         self.modules.get_mut(&self.current_module).unwrap().items.insert(id);
+        id
     }
 
     fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
@@ -1547,11 +1546,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             };
 
             trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
-            let opaque_ty_id =
-                lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
+            lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-            hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, lifetimes)
+            hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
         })
     }
 
@@ -1559,17 +1557,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// returns the lowered node-ID for the opaque type.
     fn generate_opaque_type(
         &mut self,
-        opaque_ty_node_id: NodeId,
+        opaque_ty_id: LocalDefId,
         opaque_ty_item: hir::OpaqueTy<'hir>,
         span: Span,
         opaque_ty_span: Span,
-    ) -> hir::HirId {
+    ) {
         let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
-        let opaque_ty_id = self.lower_node_id(opaque_ty_node_id);
         // Generate an `type Foo = impl Trait;` declaration.
         trace!("registering opaque type with id {:#?}", opaque_ty_id);
         let opaque_ty_item = hir::Item {
-            hir_id: opaque_ty_id,
+            def_id: opaque_ty_id,
             ident: Ident::invalid(),
             attrs: Default::default(),
             kind: opaque_ty_item_kind,
@@ -1581,7 +1578,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // automatically for all AST items. But this opaque type item
         // does not actually exist in the AST.
         self.insert_item(opaque_ty_item);
-        opaque_ty_id
     }
 
     fn lifetimes_from_impl_trait_bounds(
@@ -2010,7 +2006,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // grow.
         let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
 
-        let (opaque_ty_id, lifetime_params) = self.with_hir_id_owner(opaque_ty_node_id, |this| {
+        let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| {
             // We have to be careful to get elision right here. The
             // idea is that we create a lifetime parameter for each
             // lifetime in the return type.  So, given a return type
@@ -2061,10 +2057,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             };
 
             trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
-            let opaque_ty_id =
-                this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
+            this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
 
-            (opaque_ty_id, lifetime_params)
+            lifetime_params
         });
 
         // As documented above on the variable
@@ -2107,7 +2102,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
-        let opaque_ty_ref = hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, generic_args);
+        let opaque_ty_ref =
+            hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args);
         let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
         hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
     }
@@ -2432,7 +2428,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let mut ids: SmallVec<[hir::Stmt<'hir>; 1]> = item_ids
                     .into_iter()
                     .map(|item_id| {
-                        let item_id = hir::ItemId { id: self.lower_node_id(item_id) };
+                        let item_id = hir::ItemId {
+                            // All the items that `lower_local` finds are `impl Trait` types.
+                            def_id: self.lower_node_id(item_id).expect_owner(),
+                        };
                         self.stmt(s.span, hir::StmtKind::Item(item_id))
                     })
                     .collect();
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 01e234c9be9..180402c24fb 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1681,7 +1681,7 @@ impl<'a> State<'a> {
         self.ibox(INDENT_UNIT);
         self.s.word("[");
         self.print_inner_attributes_inline(attrs);
-        self.commasep_exprs(Inconsistent, &exprs[..]);
+        self.commasep_exprs(Inconsistent, exprs);
         self.s.word("]");
         self.end();
     }
@@ -1722,7 +1722,7 @@ impl<'a> State<'a> {
         self.print_inner_attributes_inline(attrs);
         self.commasep_cmnt(
             Consistent,
-            &fields[..],
+            fields,
             |s, field| {
                 s.print_outer_attributes(&field.attrs);
                 s.ibox(INDENT_UNIT);
@@ -1757,7 +1757,7 @@ impl<'a> State<'a> {
     fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>], attrs: &[ast::Attribute]) {
         self.popen();
         self.print_inner_attributes_inline(attrs);
-        self.commasep_exprs(Inconsistent, &exprs[..]);
+        self.commasep_exprs(Inconsistent, exprs);
         if exprs.len() == 1 {
             self.s.word(",");
         }
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 85ca1da6f1d..7e88b58c0e2 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -270,7 +270,7 @@ impl<'a, 'b> Context<'a, 'b> {
                     parse::ArgumentNamed(s) => Named(s),
                 };
 
-                let ty = Placeholder(match &arg.format.ty[..] {
+                let ty = Placeholder(match arg.format.ty {
                     "" => "Display",
                     "?" => "Debug",
                     "e" => "LowerExp",
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 0496c72cb00..0cc520e5bd1 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -312,7 +312,7 @@ pub mod printf {
                 return Some((Substitution::Escape, &s[start + 2..]));
             }
 
-            Cur::new_at(&s[..], start)
+            Cur::new_at(s, start)
         };
 
         // This is meant to be a translation of the following regex:
@@ -673,7 +673,7 @@ pub mod shell {
                 _ => { /* fall-through */ }
             }
 
-            Cur::new_at(&s[..], start)
+            Cur::new_at(s, start)
         };
 
         let at = at.at_next_cp()?;
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index df89883f0bb..c9e503a43b9 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -164,8 +164,8 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
             MonoItem::Static(def_id) => {
                 crate::constant::codegen_static(&mut cx.constants_cx, def_id)
             }
-            MonoItem::GlobalAsm(hir_id) => {
-                let item = cx.tcx.hir().expect_item(hir_id);
+            MonoItem::GlobalAsm(item_id) => {
+                let item = cx.tcx.hir().item(item_id);
                 if let rustc_hir::ItemKind::GlobalAsm(rustc_hir::GlobalAsm { asm }) = item.kind {
                     cx.global_asm.push_str(&*asm.as_str());
                     cx.global_asm.push_str("\n\n");
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 2d14ff2c022..f784d8d27cc 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -93,10 +93,9 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode) -> ! {
                 MonoItem::Static(def_id) => {
                     crate::constant::codegen_static(&mut cx.constants_cx, def_id);
                 }
-                MonoItem::GlobalAsm(hir_id) => {
-                    let item = cx.tcx.hir().expect_item(hir_id);
-                    tcx.sess
-                        .span_fatal(item.span, "Global asm is not supported in JIT mode");
+                MonoItem::GlobalAsm(item_id) => {
+                    let item = cx.tcx.hir().item(item_id);
+                    tcx.sess.span_fatal(item.span, "Global asm is not supported in JIT mode");
                 }
             }
         }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 8b737c9a2e5..5f8a11ab94e 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -11,6 +11,7 @@ use crate::llvm_util;
 use crate::type_::Type;
 use crate::LlvmCodegenBackend;
 use crate::ModuleLlvm;
+use rustc_codegen_ssa::back::link::ensure_removed;
 use rustc_codegen_ssa::back::write::{
     BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
     TargetMachineFactoryFn,
@@ -879,9 +880,7 @@ pub(crate) unsafe fn codegen(
 
                 if !config.emit_bc {
                     debug!("removing_bitcode {:?}", bc_out);
-                    if let Err(e) = fs::remove_file(&bc_out) {
-                        diag_handler.err(&format!("failed to remove bitcode: {}", e));
-                    }
+                    ensure_removed(diag_handler, &bc_out);
                 }
             }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 6c58417590e..972b9bbfe1c 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_errors::Handler;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
@@ -34,9 +35,11 @@ use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{ascii, char, env, fmt, fs, io, mem, str};
 
-pub fn remove(sess: &Session, path: &Path) {
+pub fn ensure_removed(diag_handler: &Handler, path: &Path) {
     if let Err(e) = fs::remove_file(path) {
-        sess.err(&format!("failed to remove {}: {}", path.display(), e));
+        if e.kind() != io::ErrorKind::NotFound {
+            diag_handler.err(&format!("failed to remove {}: {}", path.display(), e));
+        }
     }
 }
 
@@ -112,11 +115,11 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
         if !sess.opts.cg.save_temps {
             let remove_temps_from_module = |module: &CompiledModule| {
                 if let Some(ref obj) = module.object {
-                    remove(sess, obj);
+                    ensure_removed(sess.diagnostic(), obj);
                 }
 
                 if let Some(ref obj) = module.dwarf_object {
-                    remove(sess, obj);
+                    ensure_removed(sess.diagnostic(), obj);
                 }
             };
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 6aef5cb535a..b0aed812460 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1,4 +1,4 @@
-use super::link::{self, remove};
+use super::link::{self, ensure_removed};
 use super::linker::LinkerInfo;
 use super::lto::{self, SerializedModule};
 use super::symbol_export::symbol_name_for_instance_in_crate;
@@ -543,7 +543,7 @@ fn produce_final_output_artifacts(
             copy_gracefully(&path, &crate_output.path(output_type));
             if !sess.opts.cg.save_temps && !keep_numbered {
                 // The user just wants `foo.x`, not `foo.#module-name#.x`.
-                remove(sess, &path);
+                ensure_removed(sess.diagnostic(), &path);
             }
         } else {
             let ext = crate_output
@@ -642,19 +642,19 @@ fn produce_final_output_artifacts(
         for module in compiled_modules.modules.iter() {
             if let Some(ref path) = module.object {
                 if !keep_numbered_objects {
-                    remove(sess, path);
+                    ensure_removed(sess.diagnostic(), path);
                 }
             }
 
             if let Some(ref path) = module.dwarf_object {
                 if !keep_numbered_objects {
-                    remove(sess, path);
+                    ensure_removed(sess.diagnostic(), path);
                 }
             }
 
             if let Some(ref path) = module.bytecode {
                 if !keep_numbered_bitcode {
-                    remove(sess, path);
+                    ensure_removed(sess.diagnostic(), path);
                 }
             }
         }
@@ -662,13 +662,13 @@ fn produce_final_output_artifacts(
         if !user_wants_bitcode {
             if let Some(ref metadata_module) = compiled_modules.metadata_module {
                 if let Some(ref path) = metadata_module.bytecode {
-                    remove(sess, &path);
+                    ensure_removed(sess.diagnostic(), &path);
                 }
             }
 
             if let Some(ref allocator_module) = compiled_modules.allocator_module {
                 if let Some(ref path) = allocator_module.bytecode {
-                    remove(sess, path);
+                    ensure_removed(sess.diagnostic(), path);
                 }
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index c8219081678..9ce90669800 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let (tup, args) = args.split_last().unwrap();
             (args, Some(tup))
         } else {
-            (&args[..], None)
+            (args, None)
         };
 
         'make_args: for (i, arg) in first_args.iter().enumerate() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index f1eae605da0..ea59e183118 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -320,6 +320,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
         let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
 
+        let target_is_msvc = self.cx.sess().target.is_like_msvc;
+
         if !full_debug_info && self.cx.sess().fewer_names() {
             return None;
         }
@@ -341,11 +343,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
                         {
                             let arg_index = place.local.index() - 1;
-
-                            // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
-                            // offset in closures to account for the hidden environment?
-                            // Also, is this `+ 1` needed at all?
-                            VariableKind::ArgumentVariable(arg_index + 1)
+                            if target_is_msvc {
+                                // Rust compiler decomposes every &str or slice argument into two components:
+                                // a pointer to the memory address where the data is stored and a usize representing
+                                // the length of the str (or slice). These components will later be used to reconstruct
+                                // the original argument inside the body of the function that owns it (see the
+                                // definition of debug_introduce_local for more details).
+                                //
+                                // Since the original argument is declared inside a function rather than being passed
+                                // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
+                                // its data correctly. (See issue #81894 for an in-depth description of the problem).
+                                match *var_ty.kind() {
+                                    ty::Ref(_, inner_type, _) => match *inner_type.kind() {
+                                        ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
+                                        _ => VariableKind::ArgumentVariable(arg_index + 1),
+                                    },
+                                    _ => VariableKind::ArgumentVariable(arg_index + 1),
+                                }
+                            } else {
+                                // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
+                                // offset in closures to account for the hidden environment?
+                                // Also, is this `+ 1` needed at all?
+                                VariableKind::ArgumentVariable(arg_index + 1)
+                            }
                         } else {
                             VariableKind::LocalVariable
                         };
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 607b5459673..8e79193759e 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -30,8 +30,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
             MonoItem::Static(def_id) => {
                 cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id));
             }
-            MonoItem::GlobalAsm(hir_id) => {
-                let item = cx.tcx().hir().expect_item(hir_id);
+            MonoItem::GlobalAsm(item_id) => {
+                let item = cx.tcx().hir().item(item_id);
                 if let hir::ItemKind::GlobalAsm(ref ga) = item.kind {
                     cx.codegen_global_asm(ga);
                 } else {
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index b7edc24bc4a..17d2b3386f5 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -15,8 +15,6 @@ use rustc_span::symbol::Ident;
 use rustc_span::FileName;
 
 use std::cell::Cell;
-use std::fs::File;
-use std::io::Write;
 use std::path::Path;
 
 pub use self::PpMode::*;
@@ -237,7 +235,7 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
             pprust_hir::AnnNode::Name(_) => {}
             pprust_hir::AnnNode::Item(item) => {
                 s.s.space();
-                s.synth_comment(format!("hir_id: {}", item.hir_id));
+                s.synth_comment(format!("hir_id: {}", item.hir_id()));
             }
             pprust_hir::AnnNode::SubItem(id) => {
                 s.s.space();
@@ -375,13 +373,14 @@ fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
     (src, src_name)
 }
 
-fn write_output(out: Vec<u8>, ofile: Option<&Path>) {
+fn write_or_print(out: &str, ofile: Option<&Path>) {
     match ofile {
-        None => print!("{}", String::from_utf8(out).unwrap()),
-        Some(p) => match File::create(p) {
-            Ok(mut w) => w.write_all(&out).unwrap(),
-            Err(e) => panic!("print-print failed to open {} due to {}", p.display(), e),
-        },
+        None => print!("{}", out),
+        Some(p) => {
+            if let Err(e) = std::fs::write(p, out) {
+                panic!("print-print failed to write {} due to {}", p.display(), e);
+            }
+        }
     }
 }
 
@@ -417,7 +416,7 @@ pub fn print_after_parsing(
         unreachable!();
     };
 
-    write_output(out.into_bytes(), ofile);
+    write_or_print(&out, ofile);
 }
 
 pub fn print_after_hir_lowering<'tcx>(
@@ -477,7 +476,7 @@ pub fn print_after_hir_lowering<'tcx>(
         _ => unreachable!(),
     }
 
-    write_output(out.into_bytes(), ofile);
+    write_or_print(&out, ofile);
 }
 
 // In an ideal world, this would be a public function called by the driver after
@@ -503,7 +502,8 @@ fn print_with_analysis(
     }
     .unwrap();
 
-    write_output(out, ofile);
+    let out = std::str::from_utf8(&out).unwrap();
+    write_or_print(out, ofile);
 
     Ok(())
 }
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index d01c162b0c8..8944711f38f 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -286,6 +286,8 @@ E0538: include_str!("./error_codes/E0538.md"),
 E0539: include_str!("./error_codes/E0539.md"),
 E0541: include_str!("./error_codes/E0541.md"),
 E0542: include_str!("./error_codes/E0542.md"),
+E0543: include_str!("./error_codes/E0543.md"),
+E0545: include_str!("./error_codes/E0545.md"),
 E0546: include_str!("./error_codes/E0546.md"),
 E0547: include_str!("./error_codes/E0547.md"),
 E0550: include_str!("./error_codes/E0550.md"),
@@ -604,9 +606,7 @@ E0781: include_str!("./error_codes/E0781.md"),
     E0523,
 //  E0526, // shuffle indices are not constant
 //  E0540, // multiple rustc_deprecated attributes
-    E0543, // missing 'reason'
     E0544, // multiple stability levels
-    E0545, // incorrect 'issue'
 //  E0548, // replaced with a generic attribute input check
     // rustc_deprecated attribute must be paired with either stable or unstable
     // attribute
diff --git a/compiler/rustc_error_codes/src/error_codes/E0543.md b/compiler/rustc_error_codes/src/error_codes/E0543.md
new file mode 100644
index 00000000000..ba26f92e89f
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0543.md
@@ -0,0 +1,35 @@
+The `reason` value is missing in a stability attribute.
+
+Erroneous code example:
+
+```compile_fail,E0543
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "test")]
+
+#[stable(since = "0.1.0", feature = "_deprecated_fn")]
+#[rustc_deprecated(
+    since = "1.0.0"
+)] // invalid
+fn _deprecated_fn() {}
+```
+
+To fix this issue, you need to provide the `reason` field. Example:
+
+```
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "test")]
+
+#[stable(since = "0.1.0", feature = "_deprecated_fn")]
+#[rustc_deprecated(
+    since = "1.0.0",
+    reason = "explanation for deprecation"
+)] // ok!
+fn _deprecated_fn() {}
+```
+
+See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
+of the Book and the [Stability attributes][stability-attributes] section of the
+Rustc Dev Guide for more details.
+
+[how-rust-made-nightly]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
+[stability-attributes]: https://rustc-dev-guide.rust-lang.org/stability.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0545.md b/compiler/rustc_error_codes/src/error_codes/E0545.md
new file mode 100644
index 00000000000..9fb935a3ab1
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0545.md
@@ -0,0 +1,35 @@
+The `issue` value is incorrect in a stability attribute.
+
+Erroneous code example:
+
+```compile_fail,E0545
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "test")]
+
+#[unstable(feature = "_unstable_fn", issue = "0")] // invalid
+fn _unstable_fn() {}
+
+#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid
+fn _unstable_const_fn() {}
+```
+
+To fix this issue, you need to provide a correct value in the `issue` field.
+Example:
+
+```
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "test")]
+
+#[unstable(feature = "_unstable_fn", issue = "none")] // ok!
+fn _unstable_fn() {}
+
+#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "1")] // ok!
+fn _unstable_const_fn() {}
+```
+
+See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
+of the Book and the [Stability attributes][stability-attributes] section of the
+Rustc Dev Guide for more details.
+
+[how-rust-made-nightly]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
+[stability-attributes]: https://rustc-dev-guide.rust-lang.org/stability.html
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index c5d0927760b..f23e3b9f747 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -22,7 +22,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::Features;
-use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser};
+use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, GateOr, Parser, RecoverComma};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
@@ -914,7 +914,9 @@ pub fn parse_ast_fragment<'a>(
             }
         }
         AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
-        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?),
+        AstFragmentKind::Pat => {
+            AstFragment::Pat(this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?)
+        }
         AstFragmentKind::Arms
         | AstFragmentKind::Fields
         | AstFragmentKind::FieldPats
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 9609510d0af..6ac1c570cfe 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -619,7 +619,7 @@ pub struct WhereEqPredicate<'hir> {
 pub struct ModuleItems {
     // Use BTreeSets here so items are in the same order as in the
     // list of all items in Crate
-    pub items: BTreeSet<HirId>,
+    pub items: BTreeSet<ItemId>,
     pub trait_items: BTreeSet<TraitItemId>,
     pub impl_items: BTreeSet<ImplItemId>,
     pub foreign_items: BTreeSet<ForeignItemId>,
@@ -652,13 +652,13 @@ pub struct Crate<'hir> {
     // does, because it can affect the order in which errors are
     // detected, which in turn can make UI tests yield
     // slightly different results.
-    pub items: BTreeMap<HirId, Item<'hir>>,
+    pub items: BTreeMap<ItemId, Item<'hir>>,
 
     pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
     pub foreign_items: BTreeMap<ForeignItemId, ForeignItem<'hir>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
-    pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
+    pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
 
     /// A list of the body ids written out in the order in which they
     /// appear in the crate. If you're going to process all the bodies
@@ -668,7 +668,7 @@ pub struct Crate<'hir> {
 
     /// A list of modules written out in the order in which they
     /// appear in the crate. This includes the main crate module.
-    pub modules: BTreeMap<HirId, ModuleItems>,
+    pub modules: BTreeMap<LocalDefId, ModuleItems>,
     /// A list of proc macro HirIds, written out in the order in which
     /// they are declared in the static array generated by proc_macro_harness.
     pub proc_macros: Vec<HirId>,
@@ -677,7 +677,7 @@ pub struct Crate<'hir> {
 }
 
 impl Crate<'hir> {
-    pub fn item(&self, id: HirId) -> &Item<'hir> {
+    pub fn item(&self, id: ItemId) -> &Item<'hir> {
         &self.items[&id]
     }
 
@@ -761,16 +761,22 @@ impl Crate<'_> {
 /// A macro definition, in this crate or imported from another.
 ///
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Debug, HashStable_Generic)]
+#[derive(Debug)]
 pub struct MacroDef<'hir> {
     pub ident: Ident,
     pub vis: Visibility<'hir>,
     pub attrs: &'hir [Attribute],
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
     pub span: Span,
     pub ast: ast::MacroDef,
 }
 
+impl MacroDef<'_> {
+    pub fn hir_id(&self) -> HirId {
+        HirId::make_owner(self.def_id)
+    }
+}
+
 /// A block of statements `{ .. }`, which may have a label (in this case the
 /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
 /// the `rules` being anything but `DefaultBlock`.
@@ -1413,10 +1419,6 @@ pub struct Expr<'hir> {
     pub span: Span,
 }
 
-// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Expr<'static>, 72);
-
 impl Expr<'_> {
     pub fn precedence(&self) -> ExprPrecedence {
         match self.kind {
@@ -1911,7 +1913,14 @@ pub struct FnSig<'hir> {
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct TraitItemId {
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
+}
+
+impl TraitItemId {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
 }
 
 /// Represents an item declaration within a trait declaration,
@@ -1921,13 +1930,24 @@ pub struct TraitItemId {
 #[derive(Debug)]
 pub struct TraitItem<'hir> {
     pub ident: Ident,
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
     pub attrs: &'hir [Attribute],
     pub generics: Generics<'hir>,
     pub kind: TraitItemKind<'hir>,
     pub span: Span,
 }
 
+impl TraitItem<'_> {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
+
+    pub fn trait_item_id(&self) -> TraitItemId {
+        TraitItemId { def_id: self.def_id }
+    }
+}
+
 /// Represents a trait method's body (or just argument names).
 #[derive(Encodable, Debug, HashStable_Generic)]
 pub enum TraitFn<'hir> {
@@ -1955,14 +1975,21 @@ pub enum TraitItemKind<'hir> {
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct ImplItemId {
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
+}
+
+impl ImplItemId {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
 }
 
 /// Represents anything within an `impl` block.
 #[derive(Debug)]
 pub struct ImplItem<'hir> {
     pub ident: Ident,
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
     pub vis: Visibility<'hir>,
     pub defaultness: Defaultness,
     pub attrs: &'hir [Attribute],
@@ -1971,6 +1998,17 @@ pub struct ImplItem<'hir> {
     pub span: Span,
 }
 
+impl ImplItem<'_> {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
+
+    pub fn impl_item_id(&self) -> ImplItemId {
+        ImplItemId { def_id: self.def_id }
+    }
+}
+
 /// Represents various kinds of content within an `impl`.
 #[derive(Debug, HashStable_Generic)]
 pub enum ImplItemKind<'hir> {
@@ -2545,9 +2583,16 @@ impl VariantData<'hir> {
 // The bodies for items are stored "out of line", in a separate
 // hashmap in the `Crate`. Here we just record the hir-id of the item
 // so it can fetched later.
-#[derive(Copy, Clone, Encodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug, Hash)]
 pub struct ItemId {
-    pub id: HirId,
+    pub def_id: LocalDefId,
+}
+
+impl ItemId {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
 }
 
 /// An item
@@ -2556,13 +2601,24 @@ pub struct ItemId {
 #[derive(Debug)]
 pub struct Item<'hir> {
     pub ident: Ident,
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
     pub attrs: &'hir [Attribute],
     pub kind: ItemKind<'hir>,
     pub vis: Visibility<'hir>,
     pub span: Span,
 }
 
+impl Item<'_> {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
+
+    pub fn item_id(&self) -> ItemId {
+        ItemId { def_id: self.def_id }
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum Unsafety {
@@ -2733,7 +2789,14 @@ pub enum AssocItemKind {
 // so it can fetched later.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct ForeignItemId {
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
+}
+
+impl ForeignItemId {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
 }
 
 /// A reference from a foreign block to one of its items. This
@@ -2751,17 +2814,27 @@ pub struct ForeignItemRef<'hir> {
     pub vis: Visibility<'hir>,
 }
 
-#[derive(Debug, HashStable_Generic)]
+#[derive(Debug)]
 pub struct ForeignItem<'hir> {
-    #[stable_hasher(project(name))]
     pub ident: Ident,
     pub attrs: &'hir [Attribute],
     pub kind: ForeignItemKind<'hir>,
-    pub hir_id: HirId,
+    pub def_id: LocalDefId,
     pub span: Span,
     pub vis: Visibility<'hir>,
 }
 
+impl ForeignItem<'_> {
+    pub fn hir_id(&self) -> HirId {
+        // Items are always HIR owners.
+        HirId::make_owner(self.def_id)
+    }
+
+    pub fn foreign_item_id(&self) -> ForeignItemId {
+        ForeignItemId { def_id: self.def_id }
+    }
+}
+
 /// An item within an `extern` block.
 #[derive(Debug, HashStable_Generic)]
 pub enum ForeignItemKind<'hir> {
@@ -2871,11 +2944,12 @@ impl<'hir> Node<'hir> {
 
     pub fn hir_id(&self) -> Option<HirId> {
         match self {
-            Node::Item(Item { hir_id, .. })
-            | Node::ForeignItem(ForeignItem { hir_id, .. })
-            | Node::TraitItem(TraitItem { hir_id, .. })
-            | Node::ImplItem(ImplItem { hir_id, .. })
-            | Node::Field(StructField { hir_id, .. })
+            Node::Item(Item { def_id, .. })
+            | Node::TraitItem(TraitItem { def_id, .. })
+            | Node::ImplItem(ImplItem { def_id, .. })
+            | Node::ForeignItem(ForeignItem { def_id, .. })
+            | Node::MacroDef(MacroDef { def_id, .. }) => Some(HirId::make_owner(*def_id)),
+            Node::Field(StructField { hir_id, .. })
             | Node::AnonConst(AnonConst { hir_id, .. })
             | Node::Expr(Expr { hir_id, .. })
             | Node::Stmt(Stmt { hir_id, .. })
@@ -2885,7 +2959,6 @@ impl<'hir> Node<'hir> {
             | Node::Arm(Arm { hir_id, .. })
             | Node::Block(Block { hir_id, .. })
             | Node::Local(Local { hir_id, .. })
-            | Node::MacroDef(MacroDef { hir_id, .. })
             | Node::Lifetime(Lifetime { hir_id, .. })
             | Node::Param(Param { hir_id, .. })
             | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
@@ -2897,3 +2970,18 @@ impl<'hir> Node<'hir> {
         }
     }
 }
+
+// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+mod size_asserts {
+    rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
+    rustc_data_structures::static_assert_size!(super::Expr<'static>, 72);
+    rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
+    rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
+    rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
+
+    rustc_data_structures::static_assert_size!(super::Item<'static>, 200);
+    rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 144);
+    rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 168);
+    rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 152);
+}
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index cc8ac4cf5be..dd5cddd8525 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -18,6 +18,21 @@ pub struct HirId {
     pub local_id: ItemLocalId,
 }
 
+impl HirId {
+    pub fn expect_owner(self) -> LocalDefId {
+        assert_eq!(self.local_id.index(), 0);
+        self.owner
+    }
+
+    pub fn as_owner(self) -> Option<LocalDefId> {
+        if self.local_id.index() == 0 { Some(self.owner) } else { None }
+    }
+
+    pub fn make_owner(owner: LocalDefId) -> Self {
+        Self { owner, local_id: ItemLocalId::from_u32(0) }
+    }
+}
+
 impl fmt::Display for HirId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index f8b3f0d9b6e..6a2719c2d66 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -133,7 +133,7 @@ pub trait Map<'hir> {
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     fn find(&self, hir_id: HirId) -> Option<Node<'hir>>;
     fn body(&self, id: BodyId) -> &'hir Body<'hir>;
-    fn item(&self, id: HirId) -> &'hir Item<'hir>;
+    fn item(&self, id: ItemId) -> &'hir Item<'hir>;
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
     fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
     fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
@@ -150,7 +150,7 @@ impl<'hir> Map<'hir> for ErasedMap<'hir> {
     fn body(&self, id: BodyId) -> &'hir Body<'hir> {
         self.0.body(id)
     }
-    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+    fn item(&self, id: ItemId) -> &'hir Item<'hir> {
         self.0.item(id)
     }
     fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
@@ -269,7 +269,7 @@ pub trait Visitor<'v>: Sized {
     /// reason to override this method is if you want a nested pattern
     /// but cannot supply a `Map`; see `nested_visit_map` for advice.
     fn visit_nested_item(&mut self, id: ItemId) {
-        let opt_item = self.nested_visit_map().inter().map(|map| map.item(id.id));
+        let opt_item = self.nested_visit_map().inter().map(|map| map.item(id));
         walk_list!(self, visit_item, opt_item);
     }
 
@@ -489,7 +489,7 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
 }
 
 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
-    visitor.visit_id(macro_def.hir_id);
+    visitor.visit_id(macro_def.hir_id());
     visitor.visit_ident(macro_def.ident);
     walk_list!(visitor, visit_attribute, macro_def.attrs);
 }
@@ -565,16 +565,16 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
     visitor.visit_ident(item.ident);
     match item.kind {
         ItemKind::ExternCrate(orig_name) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             if let Some(orig_name) = orig_name {
                 visitor.visit_name(item.span, orig_name);
             }
         }
         ItemKind::Use(ref path, _) => {
-            visitor.visit_use(path, item.hir_id);
+            visitor.visit_use(path, item.hir_id());
         }
         ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_ty(typ);
             visitor.visit_nested_body(body);
         }
@@ -583,33 +583,33 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             &sig.decl,
             body_id,
             item.span,
-            item.hir_id,
+            item.hir_id(),
         ),
         ItemKind::Mod(ref module) => {
             // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
-            visitor.visit_mod(module, item.span, item.hir_id)
+            visitor.visit_mod(module, item.span, item.hir_id())
         }
         ItemKind::ForeignMod { abi: _, items } => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             walk_list!(visitor, visit_foreign_item_ref, items);
         }
         ItemKind::GlobalAsm(_) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
         }
         ItemKind::TyAlias(ref ty, ref generics) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_ty(ty);
             visitor.visit_generics(generics)
         }
         ItemKind::OpaqueTy(OpaqueTy { ref generics, bounds, .. }) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             walk_generics(visitor, generics);
             walk_list!(visitor, visit_param_bound, bounds);
         }
         ItemKind::Enum(ref enum_definition, ref generics) => {
             visitor.visit_generics(generics);
             // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
-            visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span)
+            visitor.visit_enum_def(enum_definition, generics, item.hir_id(), item.span)
         }
         ItemKind::Impl(Impl {
             unsafety: _,
@@ -622,7 +622,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             ref self_ty,
             items,
         }) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_trait_ref, of_trait);
             visitor.visit_ty(self_ty);
@@ -631,23 +631,23 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_variant_data(
                 struct_definition,
                 item.ident.name,
                 generics,
-                item.hir_id,
+                item.hir_id(),
                 item.span,
             );
         }
         ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
         }
         ItemKind::TraitAlias(ref generics, bounds) => {
-            visitor.visit_id(item.hir_id);
+            visitor.visit_id(item.hir_id());
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
         }
@@ -836,7 +836,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
 }
 
 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
-    visitor.visit_id(foreign_item.hir_id);
+    visitor.visit_id(foreign_item.hir_id());
     visitor.visit_vis(&foreign_item.vis);
     visitor.visit_ident(foreign_item.ident);
 
@@ -964,12 +964,12 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     visitor.visit_generics(&trait_item.generics);
     match trait_item.kind {
         TraitItemKind::Const(ref ty, default) => {
-            visitor.visit_id(trait_item.hir_id);
+            visitor.visit_id(trait_item.hir_id());
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_nested_body, default);
         }
         TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
-            visitor.visit_id(trait_item.hir_id);
+            visitor.visit_id(trait_item.hir_id());
             visitor.visit_fn_decl(&sig.decl);
             for &param_name in param_names {
                 visitor.visit_ident(param_name);
@@ -981,11 +981,11 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                 &sig.decl,
                 body_id,
                 trait_item.span,
-                trait_item.hir_id,
+                trait_item.hir_id(),
             );
         }
         TraitItemKind::Type(bounds, ref default) => {
-            visitor.visit_id(trait_item.hir_id);
+            visitor.visit_id(trait_item.hir_id());
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
         }
@@ -1004,7 +1004,7 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItem {
-        hir_id: _,
+        def_id: _,
         ident,
         ref vis,
         ref defaultness,
@@ -1021,7 +1021,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     visitor.visit_generics(generics);
     match *kind {
         ImplItemKind::Const(ref ty, body) => {
-            visitor.visit_id(impl_item.hir_id);
+            visitor.visit_id(impl_item.hir_id());
             visitor.visit_ty(ty);
             visitor.visit_nested_body(body);
         }
@@ -1031,11 +1031,11 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
                 &sig.decl,
                 body_id,
                 impl_item.span,
-                impl_item.hir_id,
+                impl_item.hir_id(),
             );
         }
         ImplItemKind::TyAlias(ref ty) => {
-            visitor.visit_id(impl_item.hir_id);
+            visitor.visit_id(impl_item.hir_id());
             visitor.visit_ty(ty);
         }
     }
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 439fb88039b..5fb4b8a58c2 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
 use crate::hir::{
-    BodyId, Expr, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId,
-    Ty, VisibilityKind,
+    BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, MacroDef, Mod,
+    TraitItem, TraitItemId, Ty, VisibilityKind,
 };
 use crate::hir_id::{HirId, ItemLocalId};
 use rustc_span::def_id::{DefPathHash, LocalDefId};
@@ -34,30 +34,39 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId {
+    type KeyType = DefPathHash;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+        hcx.local_def_path_hash(self.def_id)
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
-    type KeyType = (DefPathHash, ItemLocalId);
+    type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
-        self.hir_id.to_stable_hash_key(hcx)
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+        hcx.local_def_path_hash(self.def_id)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
-    type KeyType = (DefPathHash, ItemLocalId);
+    type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
-        self.hir_id.to_stable_hash_key(hcx)
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+        hcx.local_def_path_hash(self.def_id)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId {
-    type KeyType = (DefPathHash, ItemLocalId);
+    type KeyType = DefPathHash;
 
     #[inline]
-    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
-        self.hir_id.to_stable_hash_key(hcx)
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
+        hcx.local_def_path_hash(self.def_id)
     }
 }
 
@@ -82,25 +91,25 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for BodyId {
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_reference_to_item(self.id, hasher)
+        hcx.hash_reference_to_item(self.hir_id(), hasher)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_reference_to_item(self.hir_id, hasher)
+        hcx.hash_reference_to_item(self.hir_id(), hasher)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_reference_to_item(self.hir_id, hasher)
+        hcx.hash_reference_to_item(self.hir_id(), hasher)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_reference_to_item(self.hir_id, hasher)
+        hcx.hash_reference_to_item(self.hir_id(), hasher)
     }
 }
 
@@ -130,7 +139,7 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for VisibilityKind<'_>
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
+        let TraitItem { def_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
 
         hcx.hash_hir_item_like(|hcx| {
             ident.name.hash_stable(hcx, hasher);
@@ -145,7 +154,7 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         let ImplItem {
-            hir_id: _,
+            def_id: _,
             ident,
             ref vis,
             defaultness,
@@ -167,9 +176,23 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
     }
 }
 
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let ForeignItem { def_id: _, ident, ref attrs, ref kind, span, ref vis } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+        });
+    }
+}
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
+        let Item { ident, ref attrs, def_id: _, ref kind, ref vis, span } = *self;
 
         hcx.hash_hir_item_like(|hcx| {
             ident.name.hash_stable(hcx, hasher);
@@ -180,3 +203,17 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
         });
     }
 }
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for MacroDef<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let MacroDef { ident, ref attrs, def_id: _, ref ast, ref vis, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            ast.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 4595855309f..416918e3344 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -54,7 +54,7 @@ pub const NO_ANN: &dyn PpAnn = &NoAnn;
 impl PpAnn for hir::Crate<'_> {
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
         match nested {
-            Nested::Item(id) => state.print_item(self.item(id.id)),
+            Nested::Item(id) => state.print_item(self.item(id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
             Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
@@ -69,7 +69,7 @@ impl PpAnn for hir::Crate<'_> {
 impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
         match nested {
-            Nested::Item(id) => state.print_item(self.item(id.id)),
+            Nested::Item(id) => state.print_item(self.item(id)),
             Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
             Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
             Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
@@ -392,7 +392,7 @@ impl<'a> State<'a> {
                     &f.decl,
                     None,
                     &f.generic_params,
-                    &f.param_names[..],
+                    f.param_names,
                 );
             }
             hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"),
@@ -934,7 +934,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
-        self.ann.pre(self, AnnNode::SubItem(ti.hir_id));
+        self.ann.pre(self, AnnNode::SubItem(ti.hir_id()));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(ti.span.lo());
         self.print_outer_attributes(&ti.attrs);
@@ -969,11 +969,11 @@ impl<'a> State<'a> {
                 );
             }
         }
-        self.ann.post(self, AnnNode::SubItem(ti.hir_id))
+        self.ann.post(self, AnnNode::SubItem(ti.hir_id()))
     }
 
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
-        self.ann.pre(self, AnnNode::SubItem(ii.hir_id));
+        self.ann.pre(self, AnnNode::SubItem(ii.hir_id()));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(ii.span.lo());
         self.print_outer_attributes(&ii.attrs);
@@ -995,7 +995,7 @@ impl<'a> State<'a> {
                 self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
             }
         }
-        self.ann.post(self, AnnNode::SubItem(ii.hir_id))
+        self.ann.post(self, AnnNode::SubItem(ii.hir_id()))
     }
 
     pub fn print_local(&mut self, init: Option<&hir::Expr<'_>>, decl: impl Fn(&mut Self)) {
@@ -1200,7 +1200,7 @@ impl<'a> State<'a> {
         self.s.word("{");
         self.commasep_cmnt(
             Consistent,
-            &fields[..],
+            fields,
             |s, field| {
                 s.ibox(INDENT_UNIT);
                 if !field.is_shorthand {
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index f39a92b9a32..1162379d3d9 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -167,17 +167,17 @@ impl Visitor<'tcx> for IfThisChanged<'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.process_attrs(item.hir_id, &item.attrs);
+        self.process_attrs(item.hir_id(), &item.attrs);
         intravisit::walk_item(self, item);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        self.process_attrs(trait_item.hir_id, &trait_item.attrs);
+        self.process_attrs(trait_item.hir_id(), &trait_item.attrs);
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        self.process_attrs(impl_item.hir_id, &impl_item.attrs);
+        self.process_attrs(impl_item.hir_id(), &impl_item.attrs);
         intravisit::walk_impl_item(self, impl_item);
     }
 
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index e1c60050d94..8a83149d732 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -17,7 +17,7 @@ use rustc_ast::{self as ast, Attribute, NestedMetaItem};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Node as HirNode;
@@ -179,7 +179,7 @@ pub struct DirtyCleanVisitor<'tcx> {
 
 impl DirtyCleanVisitor<'tcx> {
     /// Possibly "deserialize" the attribute into a clean/dirty assertion
-    fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute) -> Option<Assertion> {
+    fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> {
         let is_clean = if self.tcx.sess.check_name(attr, sym::rustc_dirty) {
             false
         } else if self.tcx.sess.check_name(attr, sym::rustc_clean) {
@@ -207,7 +207,7 @@ impl DirtyCleanVisitor<'tcx> {
     /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels.
     fn assertion_auto(
         &mut self,
-        item_id: hir::HirId,
+        item_id: LocalDefId,
         attr: &Attribute,
         is_clean: bool,
     ) -> Assertion {
@@ -253,8 +253,9 @@ impl DirtyCleanVisitor<'tcx> {
 
     /// Return all DepNode labels that should be asserted for this item.
     /// index=0 is the "name" used for error messages
-    fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static str, Labels) {
-        let node = self.tcx.hir().get(item_id);
+    fn auto_labels(&mut self, item_id: LocalDefId, attr: &Attribute) -> (&'static str, Labels) {
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(item_id);
+        let node = self.tcx.hir().get(hir_id);
         let (name, labels) = match node {
             HirNode::Item(item) => {
                 match item.kind {
@@ -430,18 +431,17 @@ impl DirtyCleanVisitor<'tcx> {
         }
     }
 
-    fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {
-        let def_id = self.tcx.hir().local_def_id(item_id);
-        for attr in self.tcx.get_attrs(def_id.to_def_id()).iter() {
+    fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
+        for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
             let assertion = match self.assertion_maybe(item_id, attr) {
                 Some(a) => a,
                 None => continue,
             };
             self.checked_attrs.insert(attr.id);
-            for dep_node in self.dep_nodes(&assertion.clean, def_id.to_def_id()) {
+            for dep_node in self.dep_nodes(&assertion.clean, item_id.to_def_id()) {
                 self.assert_clean(item_span, dep_node);
             }
-            for dep_node in self.dep_nodes(&assertion.dirty, def_id.to_def_id()) {
+            for dep_node in self.dep_nodes(&assertion.dirty, item_id.to_def_id()) {
                 self.assert_dirty(item_span, dep_node);
             }
         }
@@ -450,19 +450,19 @@ impl DirtyCleanVisitor<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.check_item(item.hir_id, item.span);
+        self.check_item(item.def_id, item.span);
     }
 
     fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
-        self.check_item(item.hir_id, item.span);
+        self.check_item(item.def_id, item.span);
     }
 
     fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
-        self.check_item(item.hir_id, item.span);
+        self.check_item(item.def_id, item.span);
     }
 
     fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
-        self.check_item(item.hir_id, item.span);
+        self.check_item(item.def_id, item.span);
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index bd43d3c01e2..cb783847fd1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -671,7 +671,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 if !impl_candidates.is_empty() && e.span.contains(span) {
                     if let Some(expr) = exprs.first() {
                         if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
-                            if let [path_segment] = &path.segments[..] {
+                            if let [path_segment] = path.segments {
                                 let candidate_len = impl_candidates.len();
                                 let suggestions = impl_candidates.iter().map(|candidate| {
                                     format!(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
index cc8f1816bc3..0599c78ebfd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
@@ -43,7 +43,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'cx>> {
+    pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx>> {
         // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of
         // the nice region errors are required when running under the MIR borrow checker.
         self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict())
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index e3c613b1d6a..2f622231a08 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty;
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// When given a `ConcreteFailure` for a function with parameters containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
-    pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
+    pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> {
         let (span, sub, sup) = self.regions()?;
 
         debug!(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index e8e0326d978..4aecc2f40b8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -16,7 +16,7 @@ use std::fmt::{self, Write};
 impl NiceRegionError<'me, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
     /// an anonymous region, emit a descriptive diagnostic error.
-    pub(super) fn try_report_placeholder_conflict(&self) -> Option<DiagnosticBuilder<'me>> {
+    pub(super) fn try_report_placeholder_conflict(&self) -> Option<DiagnosticBuilder<'tcx>> {
         match &self.error {
             ///////////////////////////////////////////////////////////////////////////
             // NB. The ordering of cases in this match is very
@@ -30,157 +30,153 @@ impl NiceRegionError<'me, 'tcx> {
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 Some(sub_placeholder),
                 Some(sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_placeholder @ ty::RePlaceholder(_),
                 _,
                 _,
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 Some(sub_placeholder),
                 None,
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 _,
                 _,
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::SubSupConflict(
                 vid,
                 _,
                 _,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::UpperBoundUniverseConflict(
                 vid,
                 _,
                 _,
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 Some(self.tcx().mk_region(ty::ReVar(*vid))),
                 cause,
                 None,
                 Some(*sup_placeholder),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region @ ty::RePlaceholder(_),
                 sup_region @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
+            )) => self.try_report_trait_placeholder_mismatch(
                 None,
                 cause,
                 Some(*sub_region),
                 Some(*sup_region),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region @ ty::RePlaceholder(_),
                 sup_region,
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
-                Some(sup_region),
+            )) => self.try_report_trait_placeholder_mismatch(
+                (!sup_region.has_name()).then_some(sup_region),
                 cause,
-                Some(*sub_region),
+                Some(sub_region),
                 None,
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                values,
+            ),
 
             Some(RegionResolutionError::ConcreteFailure(
-                SubregionOrigin::Subtype(box TypeTrace {
-                    cause,
-                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
-                }),
+                SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sub_region,
                 sup_region @ ty::RePlaceholder(_),
-            )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
-                Some(sub_region),
+            )) => self.try_report_trait_placeholder_mismatch(
+                (!sub_region.has_name()).then_some(sub_region),
                 cause,
                 None,
-                Some(*sup_region),
-                expected.def_id,
-                expected.substs,
-                found.substs,
-            )),
+                Some(sup_region),
+                values,
+            ),
 
             _ => None,
         }
     }
 
+    fn try_report_trait_placeholder_mismatch(
+        &self,
+        vid: Option<ty::Region<'tcx>>,
+        cause: &ObligationCause<'tcx>,
+        sub_placeholder: Option<ty::Region<'tcx>>,
+        sup_placeholder: Option<ty::Region<'tcx>>,
+        value_pairs: &ValuePairs<'tcx>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        let (expected_substs, found_substs, trait_def_id) = match value_pairs {
+            ValuePairs::TraitRefs(ExpectedFound { expected, found })
+                if expected.def_id == found.def_id =>
+            {
+                (expected.substs, found.substs, expected.def_id)
+            }
+            ValuePairs::PolyTraitRefs(ExpectedFound { expected, found })
+                if expected.def_id() == found.def_id() =>
+            {
+                // It's possible that the placeholders come from a binder
+                // outside of this value pair. Use `no_bound_vars` as a
+                // simple heuristic for that.
+                (expected.no_bound_vars()?.substs, found.no_bound_vars()?.substs, expected.def_id())
+            }
+            _ => return None,
+        };
+
+        Some(self.report_trait_placeholder_mismatch(
+            vid,
+            cause,
+            sub_placeholder,
+            sup_placeholder,
+            trait_def_id,
+            expected_substs,
+            found_substs,
+        ))
+    }
+
     // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
     //   --> /home/nmatsakis/tmp/foo.rs:12:5
     //    |
@@ -190,7 +186,8 @@ impl NiceRegionError<'me, 'tcx> {
     //    = note: Due to a where-clause on the function `all`,
     //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
     //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
-    fn try_report_placeholders_trait(
+    #[instrument(level = "debug", skip(self))]
+    fn report_trait_placeholder_mismatch(
         &self,
         vid: Option<ty::Region<'tcx>>,
         cause: &ObligationCause<'tcx>,
@@ -199,28 +196,13 @@ impl NiceRegionError<'me, 'tcx> {
         trait_def_id: DefId,
         expected_substs: SubstsRef<'tcx>,
         actual_substs: SubstsRef<'tcx>,
-    ) -> DiagnosticBuilder<'me> {
-        debug!(
-            "try_report_placeholders_trait(\
-             vid={:?}, \
-             sub_placeholder={:?}, \
-             sup_placeholder={:?}, \
-             trait_def_id={:?}, \
-             expected_substs={:?}, \
-             actual_substs={:?})",
-            vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
-        );
-
+    ) -> DiagnosticBuilder<'tcx> {
         let span = cause.span(self.tcx());
         let msg = format!(
             "implementation of `{}` is not general enough",
             self.tcx().def_path_str(trait_def_id),
         );
         let mut err = self.tcx().sess.struct_span_err(span, &msg);
-        err.span_label(
-            self.tcx().def_span(trait_def_id),
-            format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)),
-        );
 
         let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
             err.span_label(span, "doesn't satisfy where-clause");
@@ -285,17 +267,13 @@ impl NiceRegionError<'me, 'tcx> {
 
         let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
 
-        debug!("try_report_placeholders_trait: actual_has_vid={:?}", actual_has_vid);
-        debug!("try_report_placeholders_trait: expected_has_vid={:?}", expected_has_vid);
-        debug!("try_report_placeholders_trait: has_sub={:?}", has_sub);
-        debug!("try_report_placeholders_trait: has_sup={:?}", has_sup);
         debug!(
-            "try_report_placeholders_trait: actual_self_ty_has_vid={:?}",
-            actual_self_ty_has_vid
-        );
-        debug!(
-            "try_report_placeholders_trait: expected_self_ty_has_vid={:?}",
-            expected_self_ty_has_vid
+            ?actual_has_vid,
+            ?expected_has_vid,
+            ?has_sub,
+            ?has_sup,
+            ?actual_self_ty_has_vid,
+            ?expected_self_ty_has_vid,
         );
 
         self.explain_actual_impl_that_was_found(
@@ -388,6 +366,8 @@ impl NiceRegionError<'me, 'tcx> {
             value: trait_ref,
         };
 
+        let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
+
         let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
         expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
         expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
@@ -403,7 +383,42 @@ impl NiceRegionError<'me, 'tcx> {
                 }
             };
 
-            let mut note = if passive_voice {
+            let mut note = if same_self_type {
+                let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
+                self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
+
+                if self_ty.value.is_closure()
+                    && self
+                        .tcx()
+                        .fn_trait_kind_from_lang_item(expected_trait_ref.value.def_id)
+                        .is_some()
+                {
+                    let closure_sig = self_ty.map(|closure| {
+                        if let ty::Closure(_, substs) = closure.kind() {
+                            self.tcx().signature_unclosure(
+                                substs.as_closure().sig(),
+                                rustc_hir::Unsafety::Normal,
+                            )
+                        } else {
+                            bug!("type is not longer closure");
+                        }
+                    });
+
+                    format!(
+                        "{}closure with signature `{}` must implement `{}`",
+                        if leading_ellipsis { "..." } else { "" },
+                        closure_sig,
+                        expected_trait_ref.map(|tr| tr.print_only_trait_path()),
+                    )
+                } else {
+                    format!(
+                        "{}`{}` must implement `{}`",
+                        if leading_ellipsis { "..." } else { "" },
+                        self_ty,
+                        expected_trait_ref.map(|tr| tr.print_only_trait_path()),
+                    )
+                }
+            } else if passive_voice {
                 format!(
                     "{}`{}` would have to be implemented for the type `{}`",
                     if leading_ellipsis { "..." } else { "" },
@@ -449,7 +464,12 @@ impl NiceRegionError<'me, 'tcx> {
                 None => true,
             };
 
-            let mut note = if passive_voice {
+            let mut note = if same_self_type {
+                format!(
+                    "...but it actually implements `{}`",
+                    actual_trait_ref.map(|tr| tr.print_only_trait_path()),
+                )
+            } else if passive_voice {
                 format!(
                     "...but `{}` is actually implemented for the type `{}`",
                     actual_trait_ref.map(|tr| tr.print_only_trait_path()),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index c6ae71ba330..fa0d5b83013 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -7,10 +7,7 @@ use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
-use rustc_hir::{
-    self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem,
-    TyKind,
-};
+use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
 use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
 use rustc_span::symbol::Ident;
 use rustc_span::{MultiSpan, Span};
@@ -234,7 +231,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
             match fn_return.kind {
                 TyKind::OpaqueDef(item_id, _) => {
-                    let item = tcx.hir().item(item_id.id);
+                    let item = tcx.hir().item(item_id);
                     let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
                         opaque
                     } else {
@@ -343,17 +340,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
         let tcx = self.tcx();
         match tcx.hir().get_if_local(def_id) {
-            Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => {
-                match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) {
+            Some(Node::ImplItem(impl_item)) => {
+                match tcx.hir().find(tcx.hir().get_parent_item(impl_item.hir_id())) {
                     Some(Node::Item(Item {
                         kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
                         ..
-                    })) => Some((*ident, self_ty)),
+                    })) => Some((impl_item.ident, self_ty)),
                     _ => None,
                 }
             }
-            Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => {
-                let parent_id = tcx.hir().get_parent_item(*hir_id);
+            Some(Node::TraitItem(trait_item)) => {
+                let parent_id = tcx.hir().get_parent_item(trait_item.hir_id());
                 match tcx.hir().find(parent_id) {
                     Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
                         // The method being called is defined in the `trait`, but the `'static`
@@ -364,8 +361,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             .hir()
                             .trait_impls(trait_did)
                             .iter()
-                            .filter_map(|impl_node| {
-                                let impl_did = tcx.hir().local_def_id(*impl_node);
+                            .filter_map(|&impl_did| {
                                 match tcx.hir().get_if_local(impl_did.to_def_id()) {
                                     Some(Node::Item(Item {
                                         kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
@@ -389,7 +385,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                             })
                             .next()
                         {
-                            Some(self_ty) => Some((*ident, self_ty)),
+                            Some(self_ty) => Some((trait_item.ident, self_ty)),
                             _ => None,
                         }
                     }
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 2cfd6bb904c..4be0e7948f7 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -15,7 +15,7 @@ pub struct Snapshot<'tcx> {
     _marker: PhantomData<&'tcx ()>,
 }
 
-/// Records the 'undo' data fora single operation that affects some form of inference variable.
+/// Records the "undo" data for a single operation that affects some form of inference variable.
 pub(crate) enum UndoLog<'tcx> {
     TypeVariables(type_variable::UndoLog<'tcx>),
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 56aa3939b22..544da4cd9aa 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -831,12 +831,11 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
             },
             {
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                    let local_def_id = tcx.hir().local_def_id(module);
-                    tcx.ensure().check_mod_loops(local_def_id);
-                    tcx.ensure().check_mod_attrs(local_def_id);
-                    tcx.ensure().check_mod_naked_functions(local_def_id);
-                    tcx.ensure().check_mod_unstable_api_usage(local_def_id);
-                    tcx.ensure().check_mod_const_bodies(local_def_id);
+                    tcx.ensure().check_mod_loops(module);
+                    tcx.ensure().check_mod_attrs(module);
+                    tcx.ensure().check_mod_naked_functions(module);
+                    tcx.ensure().check_mod_unstable_api_usage(module);
+                    tcx.ensure().check_mod_const_bodies(module);
                 });
             }
         );
@@ -861,10 +860,8 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
                         // "not all control paths return a value" is reported here.
                         //
                         // maybe move the check to a MIR pass?
-                        let local_def_id = tcx.hir().local_def_id(module);
-
-                        tcx.ensure().check_mod_liveness(local_def_id);
-                        tcx.ensure().check_mod_intrinsics(local_def_id);
+                        tcx.ensure().check_mod_liveness(module);
+                        tcx.ensure().check_mod_intrinsics(module);
                     });
                 });
             }
@@ -926,7 +923,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
             {
                 sess.time("privacy_checking_modules", || {
                     par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                        tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
+                        tcx.ensure().check_mod_privacy(module);
                     });
                 });
             }
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index de08a4c8242..d0262935c89 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -26,7 +26,7 @@ struct Finder<'tcx> {
 impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         if self.tcx.sess.contains_name(&item.attrs, sym::rustc_proc_macro_decls) {
-            self.decls = Some(item.hir_id);
+            self.decls = Some(item.hir_id());
         }
     }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 20f581625dc..71017fcde87 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -36,9 +36,9 @@ use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, Att
 use rustc_feature::{GateIssue, Stability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet};
 use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
-use rustc_hir::{HirId, HirIdSet, Node};
+use rustc_hir::{HirId, Node};
 use rustc_index::vec::Idx;
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -173,8 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..) => {
-                let def_id = cx.tcx.hir().local_def_id(it.hir_id);
-                self.check_heap_type(cx, it.span, cx.tcx.type_of(def_id))
+                self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id))
             }
             _ => (),
         }
@@ -585,9 +584,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             hir::ItemKind::Trait(.., trait_item_refs) => {
                 // Issue #11592: traits are always considered exported, even when private.
                 if let hir::VisibilityKind::Inherited = it.vis.node {
-                    self.private_traits.insert(it.hir_id);
+                    self.private_traits.insert(it.hir_id());
                     for trait_item_ref in trait_item_refs {
-                        self.private_traits.insert(trait_item_ref.id.hir_id);
+                        self.private_traits.insert(trait_item_ref.id.hir_id());
                     }
                     return;
                 }
@@ -601,7 +600,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
                     if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) {
                         if let hir::VisibilityKind::Inherited = item.vis.node {
                             for impl_item_ref in items {
-                                self.private_traits.insert(impl_item_ref.id.hir_id);
+                                self.private_traits.insert(impl_item_ref.id.hir_id());
                             }
                         }
                     }
@@ -621,23 +620,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             _ => return,
         };
 
-        let def_id = cx.tcx.hir().local_def_id(it.hir_id);
-        let (article, desc) = cx.tcx.article_and_description(def_id.to_def_id());
+        let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
 
-        self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, article, desc);
+        self.check_missing_docs_attrs(cx, Some(it.hir_id()), &it.attrs, it.span, article, desc);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
-        if self.private_traits.contains(&trait_item.hir_id) {
+        if self.private_traits.contains(&trait_item.hir_id()) {
             return;
         }
 
-        let def_id = cx.tcx.hir().local_def_id(trait_item.hir_id);
-        let (article, desc) = cx.tcx.article_and_description(def_id.to_def_id());
+        let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
 
         self.check_missing_docs_attrs(
             cx,
-            Some(trait_item.hir_id),
+            Some(trait_item.hir_id()),
             &trait_item.attrs,
             trait_item.span,
             article,
@@ -647,15 +644,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
         // If the method is an impl for a trait, don't doc.
-        if method_context(cx, impl_item.hir_id) == MethodLateContext::TraitImpl {
+        if method_context(cx, impl_item.hir_id()) == MethodLateContext::TraitImpl {
             return;
         }
 
-        let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
-        let (article, desc) = cx.tcx.article_and_description(def_id.to_def_id());
+        let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
         self.check_missing_docs_attrs(
             cx,
-            Some(impl_item.hir_id),
+            Some(impl_item.hir_id()),
             &impl_item.attrs,
             impl_item.span,
             article,
@@ -664,11 +660,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
-        let def_id = cx.tcx.hir().local_def_id(foreign_item.hir_id);
-        let (article, desc) = cx.tcx.article_and_description(def_id.to_def_id());
+        let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id());
         self.check_missing_docs_attrs(
             cx,
-            Some(foreign_item.hir_id),
+            Some(foreign_item.hir_id()),
             &foreign_item.attrs,
             foreign_item.span,
             article,
@@ -732,7 +727,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
 
 impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.access_levels.is_reachable(item.hir_id) {
+        if !cx.access_levels.is_reachable(item.hir_id()) {
             return;
         }
         let (def, ty) = match item.kind {
@@ -740,21 +735,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
                 if !ast_generics.params.is_empty() {
                     return;
                 }
-                let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
+                let def = cx.tcx.adt_def(item.def_id);
                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
             }
             hir::ItemKind::Union(_, ref ast_generics) => {
                 if !ast_generics.params.is_empty() {
                     return;
                 }
-                let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
+                let def = cx.tcx.adt_def(item.def_id);
                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
             }
             hir::ItemKind::Enum(_, ref ast_generics) => {
                 if !ast_generics.params.is_empty() {
                     return;
                 }
-                let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.hir_id));
+                let def = cx.tcx.adt_def(item.def_id);
                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
             }
             _ => return,
@@ -812,14 +807,14 @@ declare_lint! {
 
 #[derive(Default)]
 pub struct MissingDebugImplementations {
-    impling_types: Option<HirIdSet>,
+    impling_types: Option<LocalDefIdSet>,
 }
 
 impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.access_levels.is_reachable(item.hir_id) {
+        if !cx.access_levels.is_reachable(item.hir_id()) {
             return;
         }
 
@@ -834,11 +829,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
         };
 
         if self.impling_types.is_none() {
-            let mut impls = HirIdSet::default();
+            let mut impls = LocalDefIdSet::default();
             cx.tcx.for_each_impl(debug, |d| {
                 if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
                     if let Some(def_id) = ty_def.did.as_local() {
-                        impls.insert(cx.tcx.hir().local_def_id_to_hir_id(def_id));
+                        impls.insert(def_id);
                     }
                 }
             });
@@ -847,7 +842,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
             debug!("{:?}", self.impling_types);
         }
 
-        if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) {
+        if !self.impling_types.as_ref().unwrap().contains(&item.def_id) {
             cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
                 lint.build(&format!(
                     "type does not implement `{}`; consider adding `#[derive(Debug)]` \
@@ -1362,14 +1357,14 @@ impl UnreachablePub {
 
 impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
+        self.perform_lint(cx, "item", item.hir_id(), &item.vis, item.span, true);
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
         self.perform_lint(
             cx,
             "item",
-            foreign_item.hir_id,
+            foreign_item.hir_id(),
             &foreign_item.vis,
             foreign_item.span,
             true,
@@ -1381,7 +1376,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
-        self.perform_lint(cx, "item", impl_item.hir_id, &impl_item.vis, impl_item.span, false);
+        self.perform_lint(cx, "item", impl_item.hir_id(), &impl_item.vis, impl_item.span, false);
     }
 }
 
@@ -1603,8 +1598,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
         use rustc_middle::ty::PredicateKind::*;
 
         if cx.tcx.features().trivial_bounds {
-            let def_id = cx.tcx.hir().local_def_id(item.hir_id);
-            let predicates = cx.tcx.predicates_of(def_id);
+            let predicates = cx.tcx.predicates_of(item.def_id);
             for &(predicate, span) in predicates.predicates {
                 let predicate_kind_name = match predicate.kind().skip_binder() {
                     Trait(..) => "Trait",
@@ -1810,7 +1804,7 @@ declare_lint! {
 }
 
 pub struct UnnameableTestItems {
-    boundary: Option<hir::HirId>, // HirId of the item under which things are not nameable
+    boundary: Option<LocalDefId>, // Id of the item under which things are not nameable
     items_nameable: bool,
 }
 
@@ -1828,7 +1822,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
             if let hir::ItemKind::Mod(..) = it.kind {
             } else {
                 self.items_nameable = false;
-                self.boundary = Some(it.hir_id);
+                self.boundary = Some(it.def_id);
             }
             return;
         }
@@ -1841,7 +1835,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
     }
 
     fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        if !self.items_nameable && self.boundary == Some(it.hir_id) {
+        if !self.items_nameable && self.boundary == Some(it.def_id) {
             self.items_nameable = true;
         }
     }
@@ -2125,7 +2119,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
         use rustc_middle::middle::resolve_lifetime::Region;
 
         let infer_static = cx.tcx.features().infer_static_outlives_requirements;
-        let def_id = cx.tcx.hir().local_def_id(item.hir_id);
+        let def_id = item.def_id;
         if let hir::ItemKind::Struct(_, ref hir_generics)
         | hir::ItemKind::Enum(_, ref hir_generics)
         | hir::ItemKind::Union(_, ref hir_generics) = item.kind
@@ -2680,10 +2674,7 @@ impl ClashingExternDeclarations {
     /// Insert a new foreign item into the seen set. If a symbol with the same name already exists
     /// for the item, return its HirId without updating the set.
     fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
-        let hid = fi.hir_id;
-
-        let local_did = tcx.hir().local_def_id(fi.hir_id);
-        let did = local_did.to_def_id();
+        let did = fi.def_id.to_def_id();
         let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
         let name = Symbol::intern(tcx.symbol_name(instance).name);
         if let Some(&hir_id) = self.seen_decls.get(&name) {
@@ -2692,7 +2683,7 @@ impl ClashingExternDeclarations {
             // This lets us avoid emitting "knock-on" diagnostics.
             Some(hir_id)
         } else {
-            self.seen_decls.insert(name, hid)
+            self.seen_decls.insert(name, fi.hir_id())
         }
     }
 
@@ -2700,16 +2691,15 @@ impl ClashingExternDeclarations {
     /// the name specified in a #[link_name = ...] attribute if one was specified, else, just the
     /// symbol's name.
     fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName {
-        let did = tcx.hir().local_def_id(fi.hir_id);
         if let Some((overridden_link_name, overridden_link_name_span)) =
-            tcx.codegen_fn_attrs(did).link_name.map(|overridden_link_name| {
+            tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| {
                 // FIXME: Instead of searching through the attributes again to get span
                 // information, we could have codegen_fn_attrs also give span information back for
                 // where the attribute was defined. However, until this is found to be a
                 // bottleneck, this does just fine.
                 (
                     overridden_link_name,
-                    tcx.get_attrs(did.to_def_id())
+                    tcx.get_attrs(fi.def_id.to_def_id())
                         .iter()
                         .find(|at| tcx.sess.check_name(at, sym::link_name))
                         .unwrap()
@@ -2937,10 +2927,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
             let tcx = cx.tcx;
             if let Some(existing_hid) = self.insert(tcx, this_fi) {
                 let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
-                let this_decl_ty = tcx.type_of(tcx.hir().local_def_id(this_fi.hir_id));
+                let this_decl_ty = tcx.type_of(this_fi.def_id);
                 debug!(
                     "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
-                    existing_hid, existing_decl_ty, this_fi.hir_id, this_decl_ty
+                    existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty
                 );
                 // Check that the declarations match.
                 if !Self::structurally_same_type(
@@ -2962,7 +2952,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
                     // Finally, emit the diagnostic.
                     tcx.struct_span_lint_hir(
                         CLASHING_EXTERN_DECLARATIONS,
-                        this_fi.hir_id,
+                        this_fi.hir_id(),
                         get_relevant_span(this_fi),
                         |lint| {
                             let mut expected_str = DiagnosticStyledString::new();
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 3821a393efb..e019b621aa3 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -142,8 +142,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
         self.context.generics = it.kind.generics();
         let old_cached_typeck_results = self.context.cached_typeck_results.take();
         let old_enclosing_body = self.context.enclosing_body.take();
-        self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
-            cx.with_param_env(it.hir_id, |cx| {
+        self.with_lint_attrs(it.hir_id(), &it.attrs, |cx| {
+            cx.with_param_env(it.hir_id(), |cx| {
                 lint_callback!(cx, check_item, it);
                 hir_visit::walk_item(cx, it);
                 lint_callback!(cx, check_item_post, it);
@@ -155,8 +155,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     }
 
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
-        self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
-            cx.with_param_env(it.hir_id, |cx| {
+        self.with_lint_attrs(it.hir_id(), &it.attrs, |cx| {
+            cx.with_param_env(it.hir_id(), |cx| {
                 lint_callback!(cx, check_foreign_item, it);
                 hir_visit::walk_foreign_item(cx, it);
                 lint_callback!(cx, check_foreign_item_post, it);
@@ -178,7 +178,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     }
 
     fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
-        let get_item = |id: hir::ItemId| self.context.tcx.hir().item(id.id);
+        let get_item = |id: hir::ItemId| self.context.tcx.hir().item(id);
         let attrs = &s.kind.attrs(get_item);
         // See `EarlyContextAndPass::visit_stmt` for an explanation
         // of why we call `walk_stmt` outside of `with_lint_attrs`
@@ -301,8 +301,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         let generics = self.context.generics.take();
         self.context.generics = Some(&trait_item.generics);
-        self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| {
-            cx.with_param_env(trait_item.hir_id, |cx| {
+        self.with_lint_attrs(trait_item.hir_id(), &trait_item.attrs, |cx| {
+            cx.with_param_env(trait_item.hir_id(), |cx| {
                 lint_callback!(cx, check_trait_item, trait_item);
                 hir_visit::walk_trait_item(cx, trait_item);
                 lint_callback!(cx, check_trait_item_post, trait_item);
@@ -314,8 +314,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         let generics = self.context.generics.take();
         self.context.generics = Some(&impl_item.generics);
-        self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| {
-            cx.with_param_env(impl_item.hir_id, |cx| {
+        self.with_lint_attrs(impl_item.hir_id(), &impl_item.attrs, |cx| {
+            cx.with_param_env(impl_item.hir_id(), |cx| {
                 lint_callback!(cx, check_impl_item, impl_item);
                 hir_visit::walk_impl_item(cx, impl_item);
                 lint_callback!(cx, check_impl_item_post, impl_item);
@@ -496,7 +496,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
             tcx.sess.time("module_lints", || {
                 // Run per-module lints
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                    tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
+                    tcx.ensure().lint_mod(module);
                 });
             });
         },
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 1fc2bd09167..cc5b7ef0987 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -41,7 +41,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
     let push = builder.levels.push(&krate.item.attrs, &store, true);
     builder.levels.register_id(hir::CRATE_HIR_ID);
     for macro_def in krate.exported_macros {
-        builder.levels.register_id(macro_def.hir_id);
+        builder.levels.register_id(macro_def.hir_id());
     }
     intravisit::walk_crate(&mut builder, krate);
     builder.levels.pop(push);
@@ -577,13 +577,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
     }
 
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
+        self.with_lint_attrs(it.hir_id(), &it.attrs, |builder| {
             intravisit::walk_item(builder, it);
         });
     }
 
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
-        self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
+        self.with_lint_attrs(it.hir_id(), &it.attrs, |builder| {
             intravisit::walk_foreign_item(builder, it);
         })
     }
@@ -631,13 +631,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| {
+        self.with_lint_attrs(trait_item.hir_id(), &trait_item.attrs, |builder| {
             intravisit::walk_trait_item(builder, trait_item);
         });
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |builder| {
+        self.with_lint_attrs(impl_item.hir_id(), &impl_item.attrs, |builder| {
             intravisit::walk_impl_item(builder, impl_item);
         });
     }
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index b031c1108c6..e632f29e672 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -47,8 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         use rustc_middle::ty::PredicateKind::*;
 
-        let def_id = cx.tcx.hir().local_def_id(item.hir_id);
-        let predicates = cx.tcx.explicit_predicates_of(def_id);
+        let predicates = cx.tcx.explicit_predicates_of(item.def_id);
         for &(predicate, span) in predicates.predicates {
             let trait_predicate = match predicate.kind().skip_binder() {
                 Trait(trait_predicate, _constness) => trait_predicate,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index af0f5565572..792655ff35a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -225,7 +225,7 @@ fn report_bin_hex_error(
                 (t.name_str(), actually.to_string())
             }
         };
-        let mut err = lint.build(&format!("literal out of range for {}", t));
+        let mut err = lint.build(&format!("literal out of range for `{}`", t));
         err.note(&format!(
             "the literal `{}` (decimal `{}`) does not fit into \
              the type `{}` and will become `{}{}`",
@@ -238,12 +238,12 @@ fn report_bin_hex_error(
                 let (sans_suffix, _) = repr_str.split_at(pos);
                 err.span_suggestion(
                     expr.span,
-                    &format!("consider using `{}` instead", sugg_ty),
+                    &format!("consider using the type `{}` instead", sugg_ty),
                     format!("{}{}", sans_suffix, sugg_ty),
                     Applicability::MachineApplicable,
                 );
             } else {
-                err.help(&format!("consider using `{}` instead", sugg_ty));
+                err.help(&format!("consider using the type `{}` instead", sugg_ty));
             }
         }
         err.emit();
@@ -338,18 +338,23 @@ fn lint_int_literal<'tcx>(
         }
 
         cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
-            lint.build(&format!("literal out of range for `{}`", t.name_str()))
-                .note(&format!(
-                    "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
-                    cx.sess()
-                        .source_map()
-                        .span_to_snippet(lit.span)
-                        .expect("must get snippet from literal"),
-                    t.name_str(),
-                    min,
-                    max,
-                ))
-                .emit();
+            let mut err = lint.build(&format!("literal out of range for `{}`", t.name_str()));
+            err.note(&format!(
+                "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`",
+                cx.sess()
+                    .source_map()
+                    .span_to_snippet(lit.span)
+                    .expect("must get snippet from literal"),
+                t.name_str(),
+                min,
+                max,
+            ));
+            if let Some(sugg_ty) =
+                get_type_suggestion(&cx.typeck_results().node_type(e.hir_id), v, negative)
+            {
+                err.help(&format!("consider using the type `{}` instead", sugg_ty));
+            }
+            err.emit();
         });
     }
 }
@@ -1262,15 +1267,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
     fn check_foreign_item(&mut self, cx: &LateContext<'_>, it: &hir::ForeignItem<'_>) {
         let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Declaration };
-        let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
+        let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
 
         if !vis.is_internal_abi(abi) {
             match it.kind {
                 hir::ForeignItemKind::Fn(ref decl, _, _) => {
-                    vis.check_foreign_fn(it.hir_id, decl);
+                    vis.check_foreign_fn(it.hir_id(), decl);
                 }
                 hir::ForeignItemKind::Static(ref ty, _) => {
-                    vis.check_foreign_static(it.hir_id, ty.span);
+                    vis.check_foreign_static(it.hir_id(), ty.span);
                 }
                 hir::ForeignItemKind::Type => (),
             }
@@ -1308,8 +1313,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
-            let item_def_id = cx.tcx.hir().local_def_id(it.hir_id);
-            let t = cx.tcx.type_of(item_def_id);
+            let t = cx.tcx.type_of(it.def_id);
             let ty = cx.tcx.erase_regions(t);
             let layout = match cx.layout_of(ty) {
                 Ok(layout) => layout,
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 4785b6c379c..3d3071c18f2 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -4,29 +4,24 @@ use rustc_middle::middle::cstore::ForeignModule;
 use rustc_middle::ty::TyCtxt;
 
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
-    let mut collector = Collector { tcx, modules: Vec::new() };
+    let mut collector = Collector { modules: Vec::new() };
     tcx.hir().krate().visit_all_item_likes(&mut collector);
     collector.modules
 }
 
-struct Collector<'tcx> {
-    tcx: TyCtxt<'tcx>,
+struct Collector {
     modules: Vec<ForeignModule>,
 }
 
-impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
+impl ItemLikeVisitor<'tcx> for Collector {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
         let items = match it.kind {
             hir::ItemKind::ForeignMod { items, .. } => items,
             _ => return,
         };
 
-        let foreign_items =
-            items.iter().map(|it| self.tcx.hir().local_def_id(it.id.hir_id).to_def_id()).collect();
-        self.modules.push(ForeignModule {
-            foreign_items,
-            def_id: self.tcx.hir().local_def_id(it.hir_id).to_def_id(),
-        });
+        let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
+        self.modules.push(ForeignModule { foreign_items, def_id: it.def_id.to_def_id() });
     }
 
     fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 8d0994320e3..4d63b6d074a 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -53,7 +53,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
                 name: None,
                 kind: NativeLibKind::Unspecified,
                 cfg: None,
-                foreign_module: Some(self.tcx.hir().local_def_id(it.hir_id).to_def_id()),
+                foreign_module: Some(it.def_id.to_def_id()),
                 wasm_import_module: None,
             };
             let mut kind_specified = false;
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 14ca51008be..3314385dbf0 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -7,7 +7,9 @@ use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{
+    CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE,
+};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -431,7 +433,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
-        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module);
+        self.encode_info_for_mod(CRATE_DEF_ID, &krate.item.module);
 
         // Proc-macro crates only export proc-macro items, which are looked
         // up using `proc_macro_data`
@@ -866,7 +868,7 @@ impl EncodeContext<'a, 'tcx> {
 
     fn encode_variances_of(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_variances_of({:?})", def_id);
-        record!(self.tables.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
+        record!(self.tables.variances[def_id] <- self.tcx.variances_of(def_id));
     }
 
     fn encode_item_type(&mut self, def_id: DefId) {
@@ -932,9 +934,8 @@ impl EncodeContext<'a, 'tcx> {
         self.encode_inferred_outlives(def_id);
     }
 
-    fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>) {
+    fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
         let tcx = self.tcx;
-        let local_def_id = tcx.hir().local_def_id(id);
         let def_id = local_def_id.to_def_id();
         debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
 
@@ -969,7 +970,7 @@ impl EncodeContext<'a, 'tcx> {
             record!(self.tables.children[def_id] <- &[]);
         } else {
             record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
-                tcx.hir().local_def_id(item_id.id).local_def_index
+                item_id.def_id.local_def_index
             }));
         }
     }
@@ -1312,7 +1313,7 @@ impl EncodeContext<'a, 'tcx> {
                 EntryKind::Fn(self.lazy(data))
             }
             hir::ItemKind::Mod(ref m) => {
-                return self.encode_info_for_mod(item.hir_id, m);
+                return self.encode_info_for_mod(item.def_id, m);
             }
             hir::ItemKind::ForeignMod { .. } => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
@@ -1410,8 +1411,7 @@ impl EncodeContext<'a, 'tcx> {
             hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <-
                 items
                     .iter()
-                    .map(|foreign_item| tcx.hir().local_def_id(
-                        foreign_item.id.hir_id).local_def_index)
+                    .map(|foreign_item| foreign_item.id.def_id.local_def_index)
             ),
             hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
                 self.tcx.adt_def(def_id).variants.iter().map(|v| {
@@ -1494,7 +1494,7 @@ impl EncodeContext<'a, 'tcx> {
 
     /// Serialize the text of exported macros
     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
-        let def_id = self.tcx.hir().local_def_id(macro_def.hir_id).to_def_id();
+        let def_id = macro_def.def_id.to_def_id();
         record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
         self.encode_ident_span(def_id, macro_def.ident);
     }
@@ -1850,17 +1850,15 @@ impl Visitor<'tcx> for EncodeContext<'a, 'tcx> {
     }
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         intravisit::walk_item(self, item);
-        let def_id = self.tcx.hir().local_def_id(item.hir_id);
         match item.kind {
             hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
-            _ => self.encode_info_for_item(def_id.to_def_id(), item),
+            _ => self.encode_info_for_item(item.def_id.to_def_id(), item),
         }
         self.encode_addl_info_for_item(item);
     }
     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
         intravisit::walk_foreign_item(self, ni);
-        let def_id = self.tcx.hir().local_def_id(ni.hir_id);
-        self.encode_info_for_foreign_item(def_id.to_def_id(), ni);
+        self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni);
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
         intravisit::walk_generics(self, generics);
@@ -1920,7 +1918,6 @@ impl EncodeContext<'a, 'tcx> {
     /// so it's easier to do that here then to wait until we would encounter
     /// normally in the visitor walk.
     fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
-        let def_id = self.tcx.hir().local_def_id(item.hir_id);
         match item.kind {
             hir::ItemKind::Static(..)
             | hir::ItemKind::Const(..)
@@ -1936,7 +1933,7 @@ impl EncodeContext<'a, 'tcx> {
                 // no sub-item recording needed in these cases
             }
             hir::ItemKind::Enum(..) => {
-                let def = self.tcx.adt_def(def_id.to_def_id());
+                let def = self.tcx.adt_def(item.def_id.to_def_id());
                 self.encode_fields(def);
 
                 for (i, variant) in def.variants.iter_enumerated() {
@@ -1948,7 +1945,7 @@ impl EncodeContext<'a, 'tcx> {
                 }
             }
             hir::ItemKind::Struct(ref struct_def, _) => {
-                let def = self.tcx.adt_def(def_id.to_def_id());
+                let def = self.tcx.adt_def(item.def_id.to_def_id());
                 self.encode_fields(def);
 
                 // If the struct has a constructor, encode it.
@@ -1958,18 +1955,19 @@ impl EncodeContext<'a, 'tcx> {
                 }
             }
             hir::ItemKind::Union(..) => {
-                let def = self.tcx.adt_def(def_id.to_def_id());
+                let def = self.tcx.adt_def(item.def_id.to_def_id());
                 self.encode_fields(def);
             }
             hir::ItemKind::Impl { .. } => {
                 for &trait_item_def_id in
-                    self.tcx.associated_item_def_ids(def_id.to_def_id()).iter()
+                    self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
                 {
                     self.encode_info_for_impl_item(trait_item_def_id);
                 }
             }
             hir::ItemKind::Trait(..) => {
-                for &item_def_id in self.tcx.associated_item_def_ids(def_id.to_def_id()).iter() {
+                for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+                {
                     self.encode_info_for_trait_item(item_def_id);
                 }
             }
@@ -1985,15 +1983,14 @@ struct ImplVisitor<'tcx> {
 impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::Impl { .. } = item.kind {
-            let impl_id = self.tcx.hir().local_def_id(item.hir_id);
-            if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id.to_def_id()) {
+            if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
                 let simplified_self_ty =
                     ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false);
 
                 self.impls
                     .entry(trait_ref.def_id)
                     .or_default()
-                    .push((impl_id.local_def_index, simplified_self_ty));
+                    .push((item.def_id.local_def_index, simplified_self_ty));
             }
         }
     }
diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs
index 9d392c7b26b..9222ce1015e 100644
--- a/compiler/rustc_middle/src/hir/map/blocks.rs
+++ b/compiler/rustc_middle/src/hir/map/blocks.rs
@@ -215,7 +215,7 @@ impl<'a> FnLikeNode<'a> {
         match self.node {
             Node::Item(i) => match i.kind {
                 hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
-                    id: i.hir_id,
+                    id: i.hir_id(),
                     ident: i.ident,
                     decl: &sig.decl,
                     body: block,
@@ -229,13 +229,13 @@ impl<'a> FnLikeNode<'a> {
             },
             Node::TraitItem(ti) => match ti.kind {
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                    method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs)
+                    method(ti.hir_id(), ti.ident, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
             Node::ImplItem(ii) => match ii.kind {
                 hir::ImplItemKind::Fn(ref sig, body) => {
-                    method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
+                    method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                 }
                 _ => bug!("impl method FnLikeNode that is not fn-like"),
             },
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
index 872fcb0f581..a5ffa9c7a54 100644
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ b/compiler/rustc_middle/src/hir/map/collector.rs
@@ -55,22 +55,19 @@ fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V
     map[k] = Some(v);
 }
 
-fn hash(
-    hcx: &mut StableHashingContext<'_>,
-    input: impl for<'a> HashStable<StableHashingContext<'a>>,
-) -> Fingerprint {
-    let mut stable_hasher = StableHasher::new();
-    input.hash_stable(hcx, &mut stable_hasher);
-    stable_hasher.finish()
-}
-
 fn hash_body(
     hcx: &mut StableHashingContext<'_>,
     def_path_hash: DefPathHash,
     item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
     hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
 ) -> Fingerprint {
-    let hash = hash(hcx, HirItemLike { item_like: &item_like });
+    let hash = {
+        let mut stable_hasher = StableHasher::new();
+        hcx.while_hashing_hir_bodies(true, |hcx| {
+            item_like.hash_stable(hcx, &mut stable_hasher);
+        });
+        stable_hasher.finish()
+    };
     hir_body_nodes.push((def_path_hash, hash));
     hash
 }
@@ -309,7 +306,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
 
     fn visit_nested_item(&mut self, item: ItemId) {
         debug!("visit_nested_item: {:?}", item);
-        self.visit_item(self.krate.item(item.id));
+        self.visit_item(self.krate.item(item));
     }
 
     fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
@@ -338,13 +335,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
 
     fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug!("visit_item: {:?}", i);
-        debug_assert_eq!(
-            i.hir_id.owner,
-            self.definitions.opt_hir_id_to_local_def_id(i.hir_id).unwrap()
-        );
-        self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| {
-            this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash);
-            this.with_parent(i.hir_id, |this| {
+        self.with_dep_node_owner(i.def_id, i, |this, hash| {
+            let hir_id = i.hir_id();
+            this.insert_with_hash(i.span, hir_id, Node::Item(i), hash);
+            this.with_parent(hir_id, |this| {
                 if let ItemKind::Struct(ref struct_def, _) = i.kind {
                     // If this is a tuple or unit-like struct, register the constructor.
                     if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
@@ -357,14 +351,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
-        debug_assert_eq!(
-            fi.hir_id.owner,
-            self.definitions.opt_hir_id_to_local_def_id(fi.hir_id).unwrap()
-        );
-        self.with_dep_node_owner(fi.hir_id.owner, fi, |this, hash| {
-            this.insert_with_hash(fi.span, fi.hir_id, Node::ForeignItem(fi), hash);
+        self.with_dep_node_owner(fi.def_id, fi, |this, hash| {
+            this.insert_with_hash(fi.span, fi.hir_id(), Node::ForeignItem(fi), hash);
 
-            this.with_parent(fi.hir_id, |this| {
+            this.with_parent(fi.hir_id(), |this| {
                 intravisit::walk_foreign_item(this, fi);
             });
         });
@@ -394,28 +384,20 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
-        debug_assert_eq!(
-            ti.hir_id.owner,
-            self.definitions.opt_hir_id_to_local_def_id(ti.hir_id).unwrap()
-        );
-        self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| {
-            this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash);
+        self.with_dep_node_owner(ti.def_id, ti, |this, hash| {
+            this.insert_with_hash(ti.span, ti.hir_id(), Node::TraitItem(ti), hash);
 
-            this.with_parent(ti.hir_id, |this| {
+            this.with_parent(ti.hir_id(), |this| {
                 intravisit::walk_trait_item(this, ti);
             });
         });
     }
 
     fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
-        debug_assert_eq!(
-            ii.hir_id.owner,
-            self.definitions.opt_hir_id_to_local_def_id(ii.hir_id).unwrap()
-        );
-        self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| {
-            this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash);
+        self.with_dep_node_owner(ii.def_id, ii, |this, hash| {
+            this.insert_with_hash(ii.span, ii.hir_id(), Node::ImplItem(ii), hash);
 
-            this.with_parent(ii.hir_id, |this| {
+            this.with_parent(ii.hir_id(), |this| {
                 intravisit::walk_impl_item(this, ii);
             });
         });
@@ -532,15 +514,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         // Exported macros are visited directly from the crate root,
         // so they do not have `parent_node` set.
         // Find the correct enclosing module from their DefKey.
-        let def_key = self.definitions.def_key(macro_def.hir_id.owner);
+        let def_key = self.definitions.def_key(macro_def.def_id);
         let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
             self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
         });
         self.with_parent(parent, |this| {
-            this.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
+            this.with_dep_node_owner(macro_def.def_id, macro_def, |this, hash| {
                 this.insert_with_hash(
                     macro_def.span,
-                    macro_def.hir_id,
+                    macro_def.hir_id(),
                     Node::MacroDef(macro_def),
                     hash,
                 );
@@ -590,18 +572,3 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         self.visit_nested_foreign_item(id);
     }
 }
-
-struct HirItemLike<T> {
-    item_like: T,
-}
-
-impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
-where
-    T: HashStable<StableHashingContext<'hir>>,
-{
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
-        hcx.while_hashing_hir_bodies(true, |hcx| {
-            self.item_like.hash_stable(hcx, hasher);
-        });
-    }
-}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 251f8c0afe6..5c2bd575e7d 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -300,29 +300,29 @@ impl<'hir> Map<'hir> {
         self.find_entry(id).unwrap()
     }
 
-    pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
-        match self.find(id).unwrap() {
+    pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
+        match self.find(id.hir_id()).unwrap() {
             Node::Item(item) => item,
             _ => bug!(),
         }
     }
 
     pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
-        match self.find(id.hir_id).unwrap() {
+        match self.find(id.hir_id()).unwrap() {
             Node::TraitItem(item) => item,
             _ => bug!(),
         }
     }
 
     pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
-        match self.find(id.hir_id).unwrap() {
+        match self.find(id.hir_id()).unwrap() {
             Node::ImplItem(item) => item,
             _ => bug!(),
         }
     }
 
     pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
-        match self.find(id.hir_id).unwrap() {
+        match self.find(id.hir_id()).unwrap() {
             Node::ForeignItem(item) => item,
             _ => bug!(),
         }
@@ -449,7 +449,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] {
+    pub fn trait_impls(&self, trait_did: DefId) -> &'hir [LocalDefId] {
         self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
@@ -479,19 +479,19 @@ impl<'hir> Map<'hir> {
         let module = self.tcx.hir_module_items(module);
 
         for id in &module.items {
-            visitor.visit_item(self.expect_item(*id));
+            visitor.visit_item(self.item(*id));
         }
 
         for id in &module.trait_items {
-            visitor.visit_trait_item(self.expect_trait_item(id.hir_id));
+            visitor.visit_trait_item(self.trait_item(*id));
         }
 
         for id in &module.impl_items {
-            visitor.visit_impl_item(self.expect_impl_item(id.hir_id));
+            visitor.visit_impl_item(self.impl_item(*id));
         }
 
         for id in &module.foreign_items {
-            visitor.visit_foreign_item(self.expect_foreign_item(id.hir_id));
+            visitor.visit_foreign_item(self.foreign_item(*id));
         }
     }
 
@@ -500,7 +500,7 @@ impl<'hir> Map<'hir> {
         V: Visitor<'hir>,
     {
         for id in self.krate().exported_macros {
-            visitor.visit_macro_def(self.expect_macro_def(id.hir_id));
+            visitor.visit_macro_def(self.expect_macro_def(id.hir_id()));
         }
     }
 
@@ -854,22 +854,22 @@ impl<'hir> Map<'hir> {
     /// corresponding to the node-ID.
     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
         self.find_entry(id).map_or(&[], |entry| match entry.node {
-            Node::Param(a) => &a.attrs[..],
+            Node::Param(a) => a.attrs,
             Node::Local(l) => &l.attrs[..],
-            Node::Item(i) => &i.attrs[..],
-            Node::ForeignItem(fi) => &fi.attrs[..],
-            Node::TraitItem(ref ti) => &ti.attrs[..],
-            Node::ImplItem(ref ii) => &ii.attrs[..],
-            Node::Variant(ref v) => &v.attrs[..],
-            Node::Field(ref f) => &f.attrs[..],
+            Node::Item(i) => i.attrs,
+            Node::ForeignItem(fi) => fi.attrs,
+            Node::TraitItem(ref ti) => ti.attrs,
+            Node::ImplItem(ref ii) => ii.attrs,
+            Node::Variant(ref v) => v.attrs,
+            Node::Field(ref f) => f.attrs,
             Node::Expr(ref e) => &*e.attrs,
-            Node::Stmt(ref s) => s.kind.attrs(|id| self.item(id.id)),
+            Node::Stmt(ref s) => s.kind.attrs(|id| self.item(id)),
             Node::Arm(ref a) => &*a.attrs,
-            Node::GenericParam(param) => &param.attrs[..],
+            Node::GenericParam(param) => param.attrs,
             // Unit/tuple structs/variants take the attributes straight from
             // the struct/variant definition.
             Node::Ctor(..) => self.attrs(self.get_parent_item(id)),
-            Node::Crate(item) => &item.attrs[..],
+            Node::Crate(item) => item.attrs,
             Node::MacroDef(def) => def.attrs,
             Node::AnonConst(..)
             | Node::PathSegment(..)
@@ -977,7 +977,7 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
         self.body(id)
     }
 
-    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+    fn item(&self, id: ItemId) -> &'hir Item<'hir> {
         self.item(id)
     }
 
@@ -994,47 +994,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 }
 
-trait Named {
-    fn name(&self) -> Symbol;
-}
-
-impl<T: Named> Named for Spanned<T> {
-    fn name(&self) -> Symbol {
-        self.node.name()
-    }
-}
-
-impl Named for Item<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-impl Named for ForeignItem<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-impl Named for Variant<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-impl Named for StructField<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-impl Named for TraitItem<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-impl Named for ImplItem<'_> {
-    fn name(&self) -> Symbol {
-        self.ident.name
-    }
-}
-
 pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> {
     assert_eq!(cnum, LOCAL_CRATE);
 
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 6934e06d4c2..5f9cf8771ea 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -73,11 +73,7 @@ pub fn provide(providers: &mut Providers) {
     };
     providers.hir_crate = |tcx, _| tcx.untracked_crate;
     providers.index_hir = map::index_hir;
-    providers.hir_module_items = |tcx, id| {
-        let hir = tcx.hir();
-        let module = hir.local_def_id_to_hir_id(id);
-        &tcx.untracked_crate.modules[&module]
-    };
+    providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
     providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
     providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
diff --git a/compiler/rustc_middle/src/ich/impls_hir.rs b/compiler/rustc_middle/src/ich/impls_hir.rs
index d6c6cef1751..5ef70a89051 100644
--- a/compiler/rustc_middle/src/ich/impls_hir.rs
+++ b/compiler/rustc_middle/src/ich/impls_hir.rs
@@ -55,8 +55,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
         let item_ids_hash = item_ids
             .iter()
             .map(|id| {
-                let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx);
-                debug_assert_eq!(local_id, hir::ItemLocalId::from_u32(0));
+                let def_path_hash = id.to_stable_hash_key(hcx);
                 def_path_hash.0
             })
             .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b));
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index cf931ece712..26ce3c2c3db 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -40,29 +40,45 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
     struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
 }
 
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(InterpErrorInfo<'_>, 8);
+
 /// Packages the kind of error we got from the const code interpreter
 /// up with a Rust-level backtrace of where the error occurred.
 /// Thsese should always be constructed by calling `.into()` on
 /// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*`
 /// macros for this.
 #[derive(Debug)]
-pub struct InterpErrorInfo<'tcx> {
-    pub kind: InterpError<'tcx>,
+pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
+
+#[derive(Debug)]
+struct InterpErrorInfoInner<'tcx> {
+    kind: InterpError<'tcx>,
     backtrace: Option<Box<Backtrace>>,
 }
 
 impl fmt::Display for InterpErrorInfo<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.kind)
+        write!(f, "{}", self.0.kind)
     }
 }
 
-impl InterpErrorInfo<'_> {
+impl InterpErrorInfo<'tcx> {
     pub fn print_backtrace(&self) {
-        if let Some(backtrace) = self.backtrace.as_ref() {
+        if let Some(backtrace) = self.0.backtrace.as_ref() {
             print_backtrace(backtrace);
         }
     }
+
+    pub fn into_kind(self) -> InterpError<'tcx> {
+        let InterpErrorInfo(box InterpErrorInfoInner { kind, .. }) = self;
+        kind
+    }
+
+    #[inline]
+    pub fn kind(&self) -> &InterpError<'tcx> {
+        &self.0.kind
+    }
 }
 
 fn print_backtrace(backtrace: &Backtrace) {
@@ -108,7 +124,7 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
             }
         };
 
-        InterpErrorInfo { kind, backtrace }
+        InterpErrorInfo(Box::new(InterpErrorInfoInner { kind, backtrace }))
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index eb13c89544c..6c2468b9ffe 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::HirId;
+use rustc_hir::{HirId, ItemId};
 use rustc_session::config::OptLevel;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
@@ -43,7 +43,7 @@ pub enum InstantiationMode {
 pub enum MonoItem<'tcx> {
     Fn(Instance<'tcx>),
     Static(DefId),
-    GlobalAsm(HirId),
+    GlobalAsm(ItemId),
 }
 
 impl<'tcx> MonoItem<'tcx> {
@@ -71,9 +71,8 @@ impl<'tcx> MonoItem<'tcx> {
         match *self {
             MonoItem::Fn(instance) => tcx.symbol_name(instance),
             MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)),
-            MonoItem::GlobalAsm(hir_id) => {
-                let def_id = tcx.hir().local_def_id(hir_id);
-                SymbolName::new(tcx, &format!("global_asm_{:?}", def_id))
+            MonoItem::GlobalAsm(item_id) => {
+                SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id))
             }
         }
     }
@@ -178,7 +177,7 @@ impl<'tcx> MonoItem<'tcx> {
             MonoItem::Static(def_id) => {
                 def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }
-            MonoItem::GlobalAsm(hir_id) => Some(hir_id),
+            MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()),
         }
         .map(|hir_id| tcx.hir().span(hir_id))
     }
@@ -195,9 +194,9 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
             MonoItem::Static(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
-            MonoItem::GlobalAsm(node_id) => {
+            MonoItem::GlobalAsm(item_id) => {
                 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-                    node_id.hash_stable(hcx, hasher);
+                    item_id.hash_stable(hcx, hasher);
                 })
             }
         }
@@ -351,7 +350,7 @@ impl<'tcx> CodegenUnit<'tcx> {
                     MonoItem::Static(def_id) => {
                         def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
                     }
-                    MonoItem::GlobalAsm(hir_id) => Some(hir_id),
+                    MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()),
                 },
                 item.symbol_name(tcx),
             )
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f0166ec2167..475f47c65bd 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -956,7 +956,7 @@ rustc_queries! {
     /// Passing in any other crate will cause an ICE.
     ///
     /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE
-    query all_local_trait_impls(local_crate: CrateNum) -> &'tcx BTreeMap<DefId, Vec<hir::HirId>> {
+    query all_local_trait_impls(local_crate: CrateNum) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
         desc { "local trait impls" }
     }
 
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 4a131a4ec05..3b7dc25b6cf 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -289,7 +289,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
             }
             hir::TyKind::OpaqueDef(item_id, _) => {
                 self.0.push(ty);
-                let item = self.1.expect_item(item_id.id);
+                let item = self.1.item(item_id);
                 hir::intravisit::walk_item(self, item);
             }
             _ => {}
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 4f359caf31d..a6db2e3aa28 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -821,7 +821,7 @@ fn foo(&self) -> Self::T { String::new() }
                             // an assoc type as a return type (#72076).
                             if let hir::Defaultness::Default { has_value: true } = item.defaultness
                             {
-                                if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
+                                if self.type_of(item.id.def_id) == found {
                                     db.span_label(
                                         item.span,
                                         "associated type defaults can't be assumed inside the \
@@ -841,7 +841,7 @@ fn foo(&self) -> Self::T { String::new() }
             })) => {
                 for item in &items[..] {
                     if let hir::AssocItemKind::Type = item.kind {
-                        if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
+                        if self.type_of(item.id.def_id) == found {
                             db.span_label(item.span, "expected this associated type");
                             return true;
                         }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a8d9995bd0b..286041a7c54 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2107,11 +2107,9 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
             continue;
         }
 
-        if let Some(local_def_id) = hir.definitions().opt_hir_id_to_local_def_id(item.hir_id) {
-            let def_id = local_def_id.to_def_id();
-            let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
-            collect_fn(&item.ident, ns, def_id);
-        }
+        let def_id = item.def_id.to_def_id();
+        let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
+        collect_fn(&item.ident, ns, def_id);
     }
 
     // Now take care of extern crate items.
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index b41edb5deeb..efe04786933 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -427,7 +427,7 @@ impl<'sess> OnDiskCache<'sess> {
 
             fn sorted_cnums_including_local_crate(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
                 let mut cnums = vec![LOCAL_CRATE];
-                cnums.extend_from_slice(&tcx.crates()[..]);
+                cnums.extend_from_slice(tcx.crates());
                 cnums.sort_unstable();
                 // Just to be sure...
                 cnums.dedup();
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index f4d7eac0ae2..ce17a724e25 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -4,9 +4,8 @@ use crate::ty::fast_reject;
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_hir::definitions::DefPathHash;
-use rustc_hir::HirId;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -201,7 +200,7 @@ impl<'tcx> TyCtxt<'tcx> {
 pub(super) fn all_local_trait_impls<'tcx>(
     tcx: TyCtxt<'tcx>,
     krate: CrateNum,
-) -> &'tcx BTreeMap<DefId, Vec<HirId>> {
+) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
     &tcx.hir_crate(krate).trait_impls
 }
 
@@ -229,8 +228,8 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
         }
     }
 
-    for &hir_id in tcx.hir().trait_impls(trait_id) {
-        let impl_def_id = tcx.hir().local_def_id(hir_id).to_def_id();
+    for &impl_def_id in tcx.hir().trait_impls(trait_id) {
+        let impl_def_id = impl_def_id.to_def_id();
 
         let impl_self_ty = tcx.type_of(impl_def_id);
         if impl_self_ty.references_error() {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
index cbca012824f..03738f1b40a 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
@@ -634,14 +634,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     | GenericArgKind::Const(_),
                     _,
                 ) => {
-                    // I *think* that HIR lowering should ensure this
-                    // doesn't happen, even in erroneous
-                    // programs. Else we should use delay-span-bug.
-                    span_bug!(
+                    // HIR lowering sometimes doesn't catch this in erroneous
+                    // programs, so we need to use delay_span_bug here. See #82126.
+                    self.infcx.tcx.sess.delay_span_bug(
                         hir_arg.span(),
-                        "unmatched subst and hir arg: found {:?} vs {:?}",
-                        kind,
-                        hir_arg,
+                        &format!("unmatched subst and hir arg: found {:?} vs {:?}", kind, hir_arg),
                     );
                 }
             }
@@ -767,7 +764,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let hir = self.infcx.tcx.hir();
 
         if let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind {
-            let opaque_ty = hir.item(id.id);
+            let opaque_ty = hir.item(id);
             if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                 bounds:
                     [hir::GenericBound::LangItemTrait(
diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_mir/src/const_eval/error.rs
index 88af9391cad..754ed0bea84 100644
--- a/compiler/rustc_mir/src/const_eval/error.rs
+++ b/compiler/rustc_mir/src/const_eval/error.rs
@@ -84,7 +84,11 @@ impl<'tcx> ConstEvalErr<'tcx> {
     {
         error.print_backtrace();
         let stacktrace = ecx.generate_stacktrace();
-        ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) }
+        ConstEvalErr {
+            error: error.into_kind(),
+            stacktrace,
+            span: span.unwrap_or_else(|| ecx.cur_span()),
+        }
     }
 
     pub fn struct_error(
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index ed450c0c2a0..0f1c2b87426 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs
@@ -230,7 +230,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
         };
         return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| {
             let span = tcx.def_span(def_id);
-            let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
+            let error = ConstEvalErr { error: error.into_kind(), stacktrace: vec![], span };
             error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
         });
     }
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index f6b950c08c7..8e75481e323 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -245,8 +245,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         Ok(Some(match ecx.load_mir(instance.def, None) {
             Ok(body) => body,
             Err(err) => {
-                if let err_unsup!(NoMirFor(did)) = err.kind {
-                    let path = ecx.tcx.def_path_str(did);
+                if let err_unsup!(NoMirFor(did)) = err.kind() {
+                    let path = ecx.tcx.def_path_str(*did);
                     return Err(ConstEvalErrKind::NeedsRfc(format!(
                         "calling extern function `{}`",
                         path
diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs
index 6904ea5b77d..7993d4847a7 100644
--- a/compiler/rustc_mir/src/interpret/intern.rs
+++ b/compiler/rustc_mir/src/interpret/intern.rs
@@ -356,7 +356,7 @@ where
                 // an allocation, which we should avoid. When that happens,
                 // dedicated error variants should be introduced instead.
                 assert!(
-                    !error.kind.allocates(),
+                    !error.kind().allocates(),
                     "interning encountered allocating error: {}",
                     error
                 );
diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs
index dac8ddccad6..ce803c0d485 100644
--- a/compiler/rustc_mir/src/interpret/validity.rs
+++ b/compiler/rustc_mir/src/interpret/validity.rs
@@ -11,7 +11,7 @@ use std::ops::RangeInclusive;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo};
+use rustc_middle::mir::interpret::InterpError;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::symbol::{sym, Symbol};
@@ -83,14 +83,17 @@ macro_rules! try_validation {
             Ok(x) => x,
             // We catch the error and turn it into a validation failure. We are okay with
             // allocation here as this can only slow down builds that fail anyway.
-            $( $( Err(InterpErrorInfo { kind: $p, .. }) )|+ =>
-                throw_validation_failure!(
-                    $where,
-                    { $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
-                ),
-            )+
-            #[allow(unreachable_patterns)]
-            Err(e) => Err::<!, _>(e)?,
+            Err(e) => match e.kind() {
+                $(
+                    $($p)|+ =>
+                       throw_validation_failure!(
+                            $where,
+                            { $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
+                        )
+                ),+,
+                #[allow(unreachable_patterns)]
+                _ => Err::<!, _>(e)?,
+            }
         }
     }};
 }
@@ -586,8 +589,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     self.path,
                     err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
                 );
+                // Make sure we print a `ScalarMaybeUninit` (and not an `ImmTy`) in the error
+                // message below.
+                let value = value.to_scalar_or_uninit();
                 let _fn = try_validation!(
-                    value.to_scalar().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
+                    value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
                     err_ub!(InvalidFunctionPointer(..)) |
@@ -874,7 +880,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     Err(err) => {
                         // For some errors we might be able to provide extra information.
                         // (This custom logic does not fit the `try_validation!` macro.)
-                        match err.kind {
+                        match err.kind() {
                             err_ub!(InvalidUninitBytes(Some(access))) => {
                                 // Some byte was uninitialized, determine which
                                 // element that byte belongs to so we can
@@ -932,10 +938,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match visitor.visit_value(op) {
             Ok(()) => Ok(()),
             // Pass through validation failures.
-            Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err),
+            Err(err) if matches!(err.kind(), err_ub!(ValidationFailure { .. })) => Err(err),
             // Also pass through InvalidProgram, those just indicate that we could not
             // validate and each caller will know best what to do with them.
-            Err(err) if matches!(err.kind, InterpError::InvalidProgram(_)) => Err(err),
+            Err(err) if matches!(err.kind(), InterpError::InvalidProgram(_)) => Err(err),
             // Avoid other errors as those do not show *where* in the value the issue lies.
             Err(err) => {
                 err.print_backtrace();
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index 75f80f69bea..20cb989196a 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -1013,13 +1013,12 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
             | hir::ItemKind::Union(_, ref generics) => {
                 if generics.params.is_empty() {
                     if self.mode == MonoItemCollectionMode::Eager {
-                        let def_id = self.tcx.hir().local_def_id(item.hir_id);
                         debug!(
                             "RootCollector: ADT drop-glue for {}",
-                            self.tcx.def_path_str(def_id.to_def_id())
+                            self.tcx.def_path_str(item.def_id.to_def_id())
                         );
 
-                        let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty())
+                        let ty = Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
                             .ty(self.tcx, ty::ParamEnv::reveal_all());
                         visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
                     }
@@ -1028,29 +1027,28 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
             hir::ItemKind::GlobalAsm(..) => {
                 debug!(
                     "RootCollector: ItemKind::GlobalAsm({})",
-                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
+                    self.tcx.def_path_str(item.def_id.to_def_id())
                 );
-                self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.hir_id)));
+                self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.item_id())));
             }
             hir::ItemKind::Static(..) => {
-                let def_id = self.tcx.hir().local_def_id(item.hir_id).to_def_id();
-                debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id));
-                self.output.push(dummy_spanned(MonoItem::Static(def_id)));
+                debug!(
+                    "RootCollector: ItemKind::Static({})",
+                    self.tcx.def_path_str(item.def_id.to_def_id())
+                );
+                self.output.push(dummy_spanned(MonoItem::Static(item.def_id.to_def_id())));
             }
             hir::ItemKind::Const(..) => {
                 // const items only generate mono items if they are
                 // actually used somewhere. Just declaring them is insufficient.
 
                 // but even just declaring them must collect the items they refer to
-                let def_id = self.tcx.hir().local_def_id(item.hir_id);
-
-                if let Ok(val) = self.tcx.const_eval_poly(def_id.to_def_id()) {
+                if let Ok(val) = self.tcx.const_eval_poly(item.def_id.to_def_id()) {
                     collect_const_value(self.tcx, val, &mut self.output);
                 }
             }
             hir::ItemKind::Fn(..) => {
-                let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                self.push_if_root(def_id);
+                self.push_if_root(item.def_id);
             }
         }
     }
@@ -1062,8 +1060,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
 
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
         if let hir::ImplItemKind::Fn(hir::FnSig { .. }, _) = ii.kind {
-            let def_id = self.tcx.hir().local_def_id(ii.hir_id);
-            self.push_if_root(def_id);
+            self.push_if_root(ii.def_id);
         }
     }
 
@@ -1156,14 +1153,12 @@ fn create_mono_items_for_default_impls<'tcx>(
                 }
             }
 
-            let impl_def_id = tcx.hir().local_def_id(item.hir_id);
-
             debug!(
                 "create_mono_items_for_default_impls(item={})",
-                tcx.def_path_str(impl_def_id.to_def_id())
+                tcx.def_path_str(item.def_id.to_def_id())
             );
 
-            if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
+            if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
index d5a845dd76f..edd46310f20 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
@@ -314,7 +314,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
             Some(def_id)
         }
         MonoItem::Static(def_id) => Some(def_id),
-        MonoItem::GlobalAsm(hir_id) => Some(tcx.hir().local_def_id(hir_id).to_def_id()),
+        MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.to_def_id()),
     }
 }
 
@@ -405,11 +405,10 @@ fn mono_item_visibility(
                 Visibility::Hidden
             };
         }
-        MonoItem::GlobalAsm(hir_id) => {
-            let def_id = tcx.hir().local_def_id(*hir_id);
-            return if tcx.is_reachable_non_generic(def_id) {
+        MonoItem::GlobalAsm(item_id) => {
+            return if tcx.is_reachable_non_generic(item_id.def_id) {
                 *can_be_internalized = false;
-                default_visibility(tcx, def_id.to_def_id(), false)
+                default_visibility(tcx, item_id.def_id.to_def_id(), false)
             } else {
                 Visibility::Hidden
             };
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index fd5c2236902..d0a23e1359c 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -466,7 +466,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 // an allocation, which we should avoid. When that happens,
                 // dedicated error variants should be introduced instead.
                 assert!(
-                    !error.kind.allocates(),
+                    !error.kind().allocates(),
                     "const-prop encountered allocating error: {}",
                     error
                 );
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 010fe4fd524..38b7e50d786 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -289,7 +289,6 @@ use super::{PatternFoldable, PatternFolder};
 
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::OnceCell;
 
 use rustc_arena::TypedArena;
 use rustc_hir::def_id::DefId;
@@ -300,6 +299,7 @@ use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 use std::fmt;
 use std::iter::{FromIterator, IntoIterator};
+use std::lazy::OnceCell;
 
 crate struct MatchCheckCtxt<'a, 'tcx> {
     crate tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 5512e849c45..0f49386dec0 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1654,7 +1654,7 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
-        let pat = self.parse_pat(Some("argument name"))?;
+        let pat = self.parse_pat_no_top_alt(Some("argument name"))?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 20430ece05b..59fd060aa24 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1726,7 +1726,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
-            let pat = this.parse_pat(PARAM_EXPECTED)?;
+            let pat = this.parse_pat_no_top_alt(PARAM_EXPECTED)?;
             let ty = if this.eat(&token::Colon) {
                 this.parse_ty()?
             } else {
@@ -1803,7 +1803,7 @@ impl<'a> Parser<'a> {
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_top_pat(GateOr::No, RecoverComma::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@@ -1866,7 +1866,7 @@ impl<'a> Parser<'a> {
             _ => None,
         };
 
-        let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
         if !self.eat_keyword(kw::In) {
             self.error_missing_in_for_loop();
         }
@@ -1977,7 +1977,7 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
-            let pat = this.parse_top_pat(GateOr::No, RecoverComma::Yes)?;
+            let pat = this.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
                 let cond = this.parse_expr()?;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 18013f1250b..ace4134b1f6 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -14,6 +14,7 @@ use crate::lexer::UnmatchedBrace;
 pub use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 use diagnostics::Error;
+pub use pat::{GateOr, RecoverComma};
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 40dd938f000..a84ae515144 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -120,9 +120,9 @@ impl<'a> Parser<'a> {
             },
             NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
-                    NonterminalKind::Pat2018 { .. } => this.parse_pat(None),
+                    NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None),
                     NonterminalKind::Pat2021 { .. } => {
-                        this.parse_top_pat(GateOr::Yes, RecoverComma::No)
+                        this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
                     }
                     _ => unreachable!(),
                 })?)
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 317ef84742c..8874548da78 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -19,14 +19,14 @@ const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here"
 
 /// Whether or not an or-pattern should be gated when occurring in the current context.
 #[derive(PartialEq, Clone, Copy)]
-pub(super) enum GateOr {
+pub enum GateOr {
     Yes,
     No,
 }
 
 /// Whether or not to recover a `,` when parsing or-patterns.
 #[derive(PartialEq, Copy, Clone)]
-pub(super) enum RecoverComma {
+pub enum RecoverComma {
     Yes,
     No,
 }
@@ -37,80 +37,57 @@ impl<'a> Parser<'a> {
     /// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
     /// at the top level. Used when parsing the parameters of lambda expressions,
     /// functions, function pointers, and `pat` macro fragments.
-    pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
+    pub fn parse_pat_no_top_alt(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
         self.parse_pat_with_range_pat(true, expected)
     }
 
-    /// Entry point to the main pattern parser.
+    /// Parses a pattern.
+    ///
     /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
-    pub(super) fn parse_top_pat(
+    /// Used for parsing patterns in all cases when `pat<no_top_alt>` is not used.
+    ///
+    /// Note that after the FCP in <https://github.com/rust-lang/rust/issues/81415>,
+    /// a leading vert is allowed in nested or-patterns, too. This allows us to
+    /// simplify the grammar somewhat.
+    pub fn parse_pat_allow_top_alt(
         &mut self,
+        expected: Expected,
         gate_or: GateOr,
         rc: RecoverComma,
     ) -> PResult<'a, P<Pat>> {
         // Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
-        let gated_leading_vert = self.eat_or_separator(None) && gate_or == GateOr::Yes;
-        let leading_vert_span = self.prev_token.span;
-
-        // Parse the possibly-or-pattern.
-        let pat = self.parse_pat_with_or(None, gate_or, rc)?;
-
-        // If we parsed a leading `|` which should be gated,
-        // and no other gated or-pattern has been parsed thus far,
-        // then we should really gate the leading `|`.
-        // This complicated procedure is done purely for diagnostics UX.
-        if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) {
-            self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
-        }
-
-        Ok(pat)
-    }
-
-    /// Parse the pattern for a function or function pointer parameter.
-    /// Special recovery is provided for or-patterns and leading `|`.
-    pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
-        self.recover_leading_vert(None, "not allowed in a parameter pattern");
-        let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;
-
-        if let PatKind::Or(..) = &pat.kind {
-            self.ban_illegal_fn_param_or_pat(&pat);
-        }
-
-        Ok(pat)
-    }
+        let leading_vert_span =
+            if self.eat_or_separator(None) { Some(self.prev_token.span) } else { None };
 
-    /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
-    fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
-        let msg = "wrap the pattern in parenthesis";
-        let fix = format!("({})", pprust::pat_to_string(pat));
-        self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parenthesis")
-            .span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
-            .emit();
-    }
-
-    /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
-    /// Corresponds to `pat<allow_top_alt>` in RFC 2535.
-    fn parse_pat_with_or(
-        &mut self,
-        expected: Expected,
-        gate_or: GateOr,
-        rc: RecoverComma,
-    ) -> PResult<'a, P<Pat>> {
         // Parse the first pattern (`p_0`).
-        let first_pat = self.parse_pat(expected)?;
+        let first_pat = self.parse_pat_no_top_alt(expected)?;
         self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?;
 
         // If the next token is not a `|`,
         // this is not an or-pattern and we should exit here.
         if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr {
+            // If we parsed a leading `|` which should be gated,
+            // then we should really gate the leading `|`.
+            // This complicated procedure is done purely for diagnostics UX.
+            if let Some(leading_vert_span) = leading_vert_span {
+                if gate_or == GateOr::Yes && self.sess.gated_spans.is_ungated(sym::or_patterns) {
+                    self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
+                }
+
+                // If there was a leading vert, treat this as an or-pattern. This improves
+                // diagnostics.
+                let span = leading_vert_span.to(self.prev_token.span);
+                return Ok(self.mk_pat(span, PatKind::Or(vec![first_pat])));
+            }
+
             return Ok(first_pat);
         }
 
         // Parse the patterns `p_1 | ... | p_n` where `n > 0`.
-        let lo = first_pat.span;
+        let lo = leading_vert_span.unwrap_or(first_pat.span);
         let mut pats = vec![first_pat];
         while self.eat_or_separator(Some(lo)) {
-            let pat = self.parse_pat(expected).map_err(|mut err| {
+            let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| {
                 err.span_label(lo, WHILE_PARSING_OR_MSG);
                 err
             })?;
@@ -127,6 +104,62 @@ impl<'a> Parser<'a> {
         Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
     }
 
+    /// Parse the pattern for a function or function pointer parameter.
+    pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
+        // We actually do _not_ allow top-level or-patterns in function params, but we use
+        // `parse_pat_allow_top_alt` anyway so that we can detect when a user tries to use it. This
+        // allows us to print a better error message.
+        //
+        // In order to get good UX, we first recover in the case of a leading vert for an illegal
+        // top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
+        // a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
+        // separately.
+        if let token::OrOr = self.token.kind {
+            let span = self.token.span;
+            let mut err = self.struct_span_err(span, "unexpected `||` before function parameter");
+            err.span_suggestion(
+                span,
+                "remove the `||`",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
+            err.note("alternatives in or-patterns are separated with `|`, not `||`");
+            err.emit();
+            self.bump();
+        }
+
+        let pat = self.parse_pat_allow_top_alt(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;
+
+        if let PatKind::Or(..) = &pat.kind {
+            self.ban_illegal_fn_param_or_pat(&pat);
+        }
+
+        Ok(pat)
+    }
+
+    /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
+    fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
+        // If all we have a leading vert, then print a special message. This is the case if
+        // `parse_pat_allow_top_alt` returns an or-pattern with one variant.
+        let (msg, fix) = match &pat.kind {
+            PatKind::Or(pats) if pats.len() == 1 => {
+                let msg = "remove the leading `|`";
+                let fix = pprust::pat_to_string(pat);
+                (msg, fix)
+            }
+
+            _ => {
+                let msg = "wrap the pattern in parentheses";
+                let fix = format!("({})", pprust::pat_to_string(pat));
+                (msg, fix)
+            }
+        };
+
+        self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parentheses")
+            .span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
+            .emit();
+    }
+
     /// Eat the or-pattern `|` separator.
     /// If instead a `||` token is encountered, recover and pretend we parsed `|`.
     fn eat_or_separator(&mut self, lo: Option<Span>) -> bool {
@@ -179,7 +212,7 @@ impl<'a> Parser<'a> {
 
     /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
     fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
-        let mut err = self.struct_span_err(self.token.span, "unexpected token `||` after pattern");
+        let mut err = self.struct_span_err(self.token.span, "unexpected token `||` in pattern");
         err.span_suggestion(
             self.token.span,
             "use a single `|` to separate multiple alternative patterns",
@@ -244,7 +277,7 @@ impl<'a> Parser<'a> {
     /// sequence of patterns until `)` is reached.
     fn skip_pat_list(&mut self) -> PResult<'a, ()> {
         while !self.check(&token::CloseDelim(token::Paren)) {
-            self.parse_pat(None)?;
+            self.parse_pat_no_top_alt(None)?;
             if !self.eat(&token::Comma) {
                 return Ok(());
             }
@@ -252,22 +285,6 @@ impl<'a> Parser<'a> {
         Ok(())
     }
 
-    /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`.
-    /// See `parse_pat_with_or` for details on parsing or-patterns.
-    fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P<Pat>> {
-        self.recover_leading_vert(None, "only allowed in a top-level pattern");
-        self.parse_pat_with_or(None, GateOr::Yes, RecoverComma::No)
-    }
-
-    /// Recover if `|` or `||` is here.
-    /// The user is thinking that a leading `|` is allowed in this position.
-    fn recover_leading_vert(&mut self, lo: Option<Span>, ctx: &str) {
-        if let token::BinOp(token::Or) | token::OrOr = self.token.kind {
-            self.ban_illegal_vert(lo, "leading", ctx);
-            self.bump();
-        }
-    }
-
     /// A `|` or possibly `||` token shouldn't be here. Ban it.
     fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
         let span = self.token.span;
@@ -305,8 +322,9 @@ impl<'a> Parser<'a> {
             self.parse_pat_tuple_or_parens()?
         } else if self.check(&token::OpenDelim(token::Bracket)) {
             // Parse `[pat, pat,...]` as a slice pattern.
-            let (pats, _) =
-                self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?;
+            let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
+                p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
+            })?;
             PatKind::Slice(pats)
         } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
             // A rest pattern `..`.
@@ -429,7 +447,7 @@ impl<'a> Parser<'a> {
 
         // At this point we attempt to parse `@ $pat_rhs` and emit an error.
         self.bump(); // `@`
-        let mut rhs = self.parse_pat(None)?;
+        let mut rhs = self.parse_pat_no_top_alt(None)?;
         let sp = lhs.span.to(rhs.span);
 
         if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
@@ -518,8 +536,9 @@ impl<'a> Parser<'a> {
 
     /// Parse a tuple or parenthesis pattern.
     fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
-        let (fields, trailing_comma) =
-            self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
+        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
+            p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
+        })?;
 
         // Here, `(pat,)` is a tuple pattern.
         // For backward compatibility, `(..)` is a tuple pattern as well.
@@ -548,7 +567,7 @@ impl<'a> Parser<'a> {
         }
 
         // Parse the pattern we hope to be an identifier.
-        let mut pat = self.parse_pat(Some("identifier"))?;
+        let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
 
         // If we don't have `mut $ident (@ pat)?`, error.
         if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind {
@@ -793,7 +812,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
         let ident = self.parse_ident()?;
         let sub = if self.eat(&token::At) {
-            Some(self.parse_pat(Some("binding pattern"))?)
+            Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
         } else {
             None
         };
@@ -832,7 +851,9 @@ impl<'a> Parser<'a> {
         if qself.is_some() {
             return self.error_qpath_before_pat(&path, "(");
         }
-        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
+        let (fields, _) = self.parse_paren_comma_seq(|p| {
+            p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
+        })?;
         Ok(PatKind::TupleStruct(path, fields))
     }
 
@@ -998,7 +1019,7 @@ impl<'a> Parser<'a> {
             // Parsing a pattern of the form `fieldname: pat`.
             let fieldname = self.parse_field_name()?;
             self.bump();
-            let pat = self.parse_pat_with_or_inner()?;
+            let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?;
             hi = pat.span;
             (pat, fieldname, false)
         } else {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index e36ebd5e481..2e00ddfaacc 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -220,7 +220,7 @@ impl<'a> Parser<'a> {
     /// Parses a local variable declaration.
     fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
 
         let (err, ty) = if self.eat(&token::Colon) {
             // Save the state of the parser before parsing type normally, in case there is a `:`
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2c79eeeb0e6..bf9b7e588bd 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -29,7 +29,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
     match impl_item.kind {
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
-            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
+            let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
             let containing_item = tcx.hir().expect_item(parent_hir_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
@@ -1058,7 +1058,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         let target = Target::from_item(item);
         self.check_attributes(
-            item.hir_id,
+            item.hir_id(),
             item.attrs,
             &item.span,
             target,
@@ -1081,7 +1081,13 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
         let target = Target::from_trait_item(trait_item);
-        self.check_attributes(trait_item.hir_id, &trait_item.attrs, &trait_item.span, target, None);
+        self.check_attributes(
+            trait_item.hir_id(),
+            &trait_item.attrs,
+            &trait_item.span,
+            target,
+            None,
+        );
         intravisit::walk_trait_item(self, trait_item)
     }
 
@@ -1104,7 +1110,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
     fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) {
         let target = Target::from_foreign_item(f_item);
         self.check_attributes(
-            f_item.hir_id,
+            f_item.hir_id(),
             &f_item.attrs,
             &f_item.span,
             target,
@@ -1115,7 +1121,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         let target = target_from_impl_item(self.tcx, impl_item);
-        self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None);
+        self.check_attributes(impl_item.hir_id(), &impl_item.attrs, &impl_item.span, target, None);
         intravisit::walk_impl_item(self, impl_item)
     }
 
@@ -1149,7 +1155,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
         self.check_attributes(
-            macro_def.hir_id,
+            macro_def.hir_id(),
             macro_def.attrs,
             &macro_def.span,
             Target::MacroDef,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 0d096a0556b..d51b501f7ae 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -188,8 +188,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         match node {
             Node::Item(item) => match item.kind {
                 hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
-                    let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                    let def = self.tcx.adt_def(def_id);
+                    let def = self.tcx.adt_def(item.def_id);
                     self.repr_has_repr_c = def.repr.c();
 
                     intravisit::walk_item(self, &item);
@@ -329,7 +328,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         if let TyKind::OpaqueDef(item_id, _) = ty.kind {
-            let item = self.tcx.hir().expect_item(item_id.id);
+            let item = self.tcx.hir().item(item_id);
             intravisit::walk_item(self, item);
         }
         intravisit::walk_ty(self, ty);
@@ -395,9 +394,10 @@ struct LifeSeeder<'k, 'tcx> {
 
 impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx, item.hir_id, &item.attrs);
+        let allow_dead_code =
+            has_allow_dead_code_or_lang_attr(self.tcx, item.hir_id(), &item.attrs);
         if allow_dead_code {
-            self.worklist.push(item.hir_id);
+            self.worklist.push(item.hir_id());
         }
         match item.kind {
             hir::ItemKind::Enum(ref enum_def, _) => {
@@ -413,24 +413,24 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
             }
             hir::ItemKind::Impl(hir::Impl { ref of_trait, items, .. }) => {
                 if of_trait.is_some() {
-                    self.worklist.push(item.hir_id);
+                    self.worklist.push(item.hir_id());
                 }
                 for impl_item_ref in items {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
                     if of_trait.is_some()
                         || has_allow_dead_code_or_lang_attr(
                             self.tcx,
-                            impl_item.hir_id,
+                            impl_item.hir_id(),
                             &impl_item.attrs,
                         )
                     {
-                        self.worklist.push(impl_item_ref.id.hir_id);
+                        self.worklist.push(impl_item_ref.id.hir_id());
                     }
                 }
             }
             hir::ItemKind::Struct(ref variant_data, _) => {
                 if let Some(ctor_hir_id) = variant_data.ctor_hir_id() {
-                    self.struct_constructors.insert(ctor_hir_id, item.hir_id);
+                    self.struct_constructors.insert(ctor_hir_id, item.hir_id());
                 }
             }
             _ => (),
@@ -440,9 +440,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         use hir::TraitItemKind::{Const, Fn};
         if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
-            && has_allow_dead_code_or_lang_attr(self.tcx, trait_item.hir_id, &trait_item.attrs)
+            && has_allow_dead_code_or_lang_attr(self.tcx, trait_item.hir_id(), &trait_item.attrs)
         {
-            self.worklist.push(trait_item.hir_id);
+            self.worklist.push(trait_item.hir_id());
         }
     }
 
@@ -453,9 +453,13 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
         use hir::ForeignItemKind::{Fn, Static};
         if matches!(foreign_item.kind, Static(..) | Fn(..))
-            && has_allow_dead_code_or_lang_attr(self.tcx, foreign_item.hir_id, &foreign_item.attrs)
+            && has_allow_dead_code_or_lang_attr(
+                self.tcx,
+                foreign_item.hir_id(),
+                &foreign_item.attrs,
+            )
         {
-            self.worklist.push(foreign_item.hir_id);
+            self.worklist.push(foreign_item.hir_id());
         }
     }
 }
@@ -525,7 +529,7 @@ impl DeadVisitor<'tcx> {
                 | hir::ItemKind::Struct(..)
                 | hir::ItemKind::Union(..)
         );
-        should_warn && !self.symbol_is_live(item.hir_id)
+        should_warn && !self.symbol_is_live(item.hir_id())
     }
 
     fn should_warn_about_field(&mut self, field: &hir::StructField<'_>) -> bool {
@@ -542,8 +546,8 @@ impl DeadVisitor<'tcx> {
     }
 
     fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool {
-        !self.symbol_is_live(fi.hir_id)
-            && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id, &fi.attrs)
+        !self.symbol_is_live(fi.hir_id())
+            && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id(), &fi.attrs)
     }
 
     // id := HIR id of an item's definition.
@@ -627,7 +631,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 hir::ItemKind::Struct(..) => "constructed", // Issue #52325
                 _ => "used",
             };
-            self.warn_dead_code(item.hir_id, span, item.ident.name, participle);
+            self.warn_dead_code(item.hir_id(), span, item.ident.name, participle);
         } else {
             // Only continue if we didn't warn
             intravisit::walk_item(self, item);
@@ -649,7 +653,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
 
     fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
         if self.should_warn_about_foreign_item(fi) {
-            self.warn_dead_code(fi.hir_id, fi.span, fi.ident.name, "used");
+            self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used");
         }
         intravisit::walk_foreign_item(self, fi);
     }
@@ -664,9 +668,9 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         match impl_item.kind {
             hir::ImplItemKind::Const(_, body_id) => {
-                if !self.symbol_is_live(impl_item.hir_id) {
+                if !self.symbol_is_live(impl_item.hir_id()) {
                     self.warn_dead_code(
-                        impl_item.hir_id,
+                        impl_item.hir_id(),
                         impl_item.span,
                         impl_item.ident.name,
                         "used",
@@ -675,7 +679,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Fn(_, body_id) => {
-                if !self.symbol_is_live(impl_item.hir_id) {
+                if !self.symbol_is_live(impl_item.hir_id()) {
                     // FIXME(66095): Because impl_item.span is annotated with things
                     // like expansion data, and ident.span isn't, we use the
                     // def_span method if it's part of a macro invocation
@@ -687,7 +691,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                     } else {
                         impl_item.ident.span
                     };
-                    self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "used");
+                    self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used");
                 }
                 self.visit_nested_body(body_id)
             }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 699c96bc49d..3ec7ea39248 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -16,7 +16,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
 
 struct DiagnosticItemCollector<'tcx> {
@@ -27,19 +27,19 @@ struct DiagnosticItemCollector<'tcx> {
 
 impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        self.observe_item(&item.attrs, item.hir_id);
+        self.observe_item(&item.attrs, item.def_id);
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        self.observe_item(&trait_item.attrs, trait_item.hir_id);
+        self.observe_item(&trait_item.attrs, trait_item.def_id);
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        self.observe_item(&impl_item.attrs, impl_item.hir_id);
+        self.observe_item(&impl_item.attrs, impl_item.def_id);
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
-        self.observe_item(foreign_item.attrs, foreign_item.hir_id);
+        self.observe_item(foreign_item.attrs, foreign_item.def_id);
     }
 }
 
@@ -48,9 +48,8 @@ impl<'tcx> DiagnosticItemCollector<'tcx> {
         DiagnosticItemCollector { tcx, items: Default::default() }
     }
 
-    fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) {
+    fn observe_item(&mut self, attrs: &[ast::Attribute], def_id: LocalDefId) {
         if let Some(name) = extract(&self.tcx.sess, attrs) {
-            let def_id = self.tcx.hir().local_def_id(hir_id);
             // insert into our table
             collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
         }
@@ -106,7 +105,7 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
     tcx.hir().krate().visit_all_item_likes(&mut collector);
 
     for m in tcx.hir().krate().exported_macros {
-        collector.observe_item(m.attrs, m.hir_id);
+        collector.observe_item(m.attrs, m.def_id);
     }
 
     collector.items
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 5ff631a2457..0d3a7ea3a8a 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -32,8 +32,7 @@ struct EntryContext<'a, 'tcx> {
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
-        let def_id = self.map.local_def_id(item.hir_id);
-        let def_key = self.map.def_key(def_id);
+        let def_key = self.map.def_key(item.def_id);
         let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
         find_item(item, self, at_root);
     }
@@ -116,18 +115,18 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
         }
         EntryPointType::MainNamed => {
             if ctxt.main_fn.is_none() {
-                ctxt.main_fn = Some((item.hir_id, item.span));
+                ctxt.main_fn = Some((item.hir_id(), item.span));
             } else {
                 struct_span_err!(ctxt.session, item.span, E0136, "multiple `main` functions")
                     .emit();
             }
         }
         EntryPointType::OtherMain => {
-            ctxt.non_main_fns.push((item.hir_id, item.span));
+            ctxt.non_main_fns.push((item.hir_id(), item.span));
         }
         EntryPointType::MainAttr => {
             if ctxt.attr_main_fn.is_none() {
-                ctxt.attr_main_fn = Some((item.hir_id, item.span));
+                ctxt.attr_main_fn = Some((item.hir_id(), item.span));
             } else {
                 struct_span_err!(
                     ctxt.session,
@@ -142,7 +141,7 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
         }
         EntryPointType::Start => {
             if ctxt.start_fn.is_none() {
-                ctxt.start_fn = Some((item.hir_id, item.span));
+                ctxt.start_fn = Some((item.hir_id(), item.span));
             } else {
                 struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
                     .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index fdd6c238055..79e3b5952ac 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -14,12 +14,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     let errors = Lock::new(Vec::new());
     let hir_map = tcx.hir();
 
-    par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
-        let local_def_id = hir_map.local_def_id(*module_id);
-        hir_map.visit_item_likes_in_module(
-            local_def_id,
-            &mut OuterVisitor { hir_map, errors: &errors },
-        );
+    par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
+        hir_map
+            .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
     });
 
     let errors = errors.into_inner();
@@ -56,22 +53,22 @@ impl<'a, 'hir> OuterVisitor<'a, 'hir> {
 impl<'a, 'hir> ItemLikeVisitor<'hir> for OuterVisitor<'a, 'hir> {
     fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
-        inner_visitor.check(i.hir_id, |this| intravisit::walk_item(this, i));
+        inner_visitor.check(i.hir_id(), |this| intravisit::walk_item(this, i));
     }
 
     fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
-        inner_visitor.check(i.hir_id, |this| intravisit::walk_trait_item(this, i));
+        inner_visitor.check(i.hir_id(), |this| intravisit::walk_trait_item(this, i));
     }
 
     fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
-        inner_visitor.check(i.hir_id, |this| intravisit::walk_impl_item(this, i));
+        inner_visitor.check(i.hir_id(), |this| intravisit::walk_impl_item(this, i));
     }
 
     fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
         let mut inner_visitor = self.new_inner_visitor(self.hir_map);
-        inner_visitor.check(i.hir_id, |this| intravisit::walk_foreign_item(this, i));
+        inner_visitor.check(i.hir_id(), |this| intravisit::walk_foreign_item(this, i));
     }
 }
 
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 1d02c9aa637..e35ad10968d 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -100,7 +100,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_nested_item(&mut self, id: hir::ItemId) {
-        let nested_item = self.krate.unwrap().item(id.id);
+        let nested_item = self.krate.unwrap().item(id);
         self.visit_item(nested_item)
     }
 
@@ -120,7 +120,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_item(&mut self, i: &'v hir::Item<'v>) {
-        self.record("Item", Id::Node(i.hir_id), i);
+        self.record("Item", Id::Node(i.hir_id()), i);
         hir_visit::walk_item(self, i)
     }
 
@@ -130,7 +130,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
-        self.record("ForeignItem", Id::Node(i.hir_id), i);
+        self.record("ForeignItem", Id::Node(i.hir_id()), i);
         hir_visit::walk_foreign_item(self, i)
     }
 
@@ -187,12 +187,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
-        self.record("TraitItem", Id::Node(ti.hir_id), ti);
+        self.record("TraitItem", Id::Node(ti.hir_id()), ti);
         hir_visit::walk_trait_item(self, ti)
     }
 
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
-        self.record("ImplItem", Id::Node(ii.hir_id), ii);
+        self.record("ImplItem", Id::Node(ii.hir_id()), ii);
         hir_visit::walk_impl_item(self, ii)
     }
 
@@ -246,7 +246,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'v>) {
-        self.record("MacroDef", Id::Node(macro_def.hir_id), macro_def);
+        self.record("MacroDef", Id::Node(macro_def.hir_id()), macro_def);
         hir_visit::walk_macro_def(self, macro_def)
     }
 }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 3132661e5f5..8e2ad7f783e 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -30,7 +30,7 @@ struct LanguageItemCollector<'tcx> {
 
 impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        self.check_for_lang(Target::from_item(item), item.hir_id, item.attrs);
+        self.check_for_lang(Target::from_item(item), item.hir_id(), item.attrs);
 
         if let hir::ItemKind::Enum(def, ..) = &item.kind {
             for variant in def.variants {
@@ -42,7 +42,7 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         self.check_for_lang(
             Target::from_trait_item(trait_item),
-            trait_item.hir_id,
+            trait_item.hir_id(),
             trait_item.attrs,
         )
     }
@@ -50,7 +50,7 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         self.check_for_lang(
             target_from_impl_item(self.tcx, impl_item),
-            impl_item.hir_id,
+            impl_item.hir_id(),
             impl_item.attrs,
         )
     }
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 9e83cbd6680..18c1d647060 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -21,16 +21,14 @@ struct LayoutTest<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
-
         match item.kind {
             ItemKind::TyAlias(..)
             | ItemKind::Enum(..)
             | ItemKind::Struct(..)
             | ItemKind::Union(..) => {
-                for attr in self.tcx.get_attrs(item_def_id.to_def_id()).iter() {
+                for attr in self.tcx.get_attrs(item.def_id.to_def_id()).iter() {
                     if self.tcx.sess.check_name(attr, sym::rustc_layout) {
-                        self.dump_layout_of(item_def_id, item, attr);
+                        self.dump_layout_of(item.def_id, item, attr);
                     }
                 }
             }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index eb24c51c54c..20aaaea5b98 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -31,7 +31,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: &Codege
     match item.kind {
         hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true,
         hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
-            let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
+            let generics = tcx.generics_of(item.def_id);
             generics.requires_monomorphization(tcx)
         }
         _ => false,
@@ -43,8 +43,8 @@ fn method_might_be_inlined(
     impl_item: &hir::ImplItem<'_>,
     impl_src: LocalDefId,
 ) -> bool {
-    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner.to_def_id());
-    let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id));
+    let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id());
+    let generics = tcx.generics_of(impl_item.def_id);
     if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
         return true;
     }
@@ -218,8 +218,7 @@ impl<'tcx> ReachableContext<'tcx> {
                 } else {
                     false
                 };
-                let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
+                let codegen_attrs = self.tcx.codegen_fn_attrs(item.def_id);
                 let is_extern = codegen_attrs.contains_extern_indicator();
                 let std_internal =
                     codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
@@ -239,9 +238,11 @@ impl<'tcx> ReachableContext<'tcx> {
             Node::Item(item) => {
                 match item.kind {
                     hir::ItemKind::Fn(.., body) => {
-                        let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                        if item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id))
-                        {
+                        if item_might_be_inlined(
+                            self.tcx,
+                            &item,
+                            self.tcx.codegen_fn_attrs(item.def_id),
+                        ) {
                             self.visit_nested_body(body);
                         }
                     }
@@ -341,23 +342,21 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
         // Anything which has custom linkage gets thrown on the worklist no
         // matter where it is in the crate, along with "special std symbols"
         // which are currently akin to allocator symbols.
-        let def_id = self.tcx.hir().local_def_id(item.hir_id);
-        let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
+        let codegen_attrs = self.tcx.codegen_fn_attrs(item.def_id);
         if codegen_attrs.contains_extern_indicator()
             || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
         {
-            self.worklist.push(def_id);
+            self.worklist.push(item.def_id);
         }
 
         // We need only trait impls here, not inherent impls, and only non-exported ones
         if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
             item.kind
         {
-            if !self.access_levels.is_reachable(item.hir_id) {
+            if !self.access_levels.is_reachable(item.hir_id()) {
                 // FIXME(#53488) remove `let`
                 let tcx = self.tcx;
-                self.worklist
-                    .extend(items.iter().map(|ii_ref| tcx.hir().local_def_id(ii_ref.id.hir_id)));
+                self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id));
 
                 let trait_def_id = match trait_ref.path.res {
                     Res::Def(DefKind::Trait, def_id) => def_id,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index e1d03e35048..f538427efd9 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -376,7 +376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         }
 
         self.annotate(
-            i.hir_id,
+            i.hir_id(),
             &i.attrs,
             i.span,
             kind,
@@ -389,7 +389,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
         self.annotate(
-            ti.hir_id,
+            ti.hir_id(),
             &ti.attrs,
             ti.span,
             AnnotationKind::Required,
@@ -405,7 +405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
         let kind =
             if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
         self.annotate(
-            ii.hir_id,
+            ii.hir_id(),
             &ii.attrs,
             ii.span,
             kind,
@@ -459,7 +459,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         self.annotate(
-            i.hir_id,
+            i.hir_id(),
             &i.attrs,
             i.span,
             AnnotationKind::Required,
@@ -473,7 +473,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         self.annotate(
-            md.hir_id,
+            md.hir_id(),
             &md.attrs,
             md.span,
             AnnotationKind::Required,
@@ -556,7 +556,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
             hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
                 | hir::ItemKind::ForeignMod { .. }
         ) {
-            self.check_missing_stability(i.hir_id, i.span);
+            self.check_missing_stability(i.hir_id(), i.span);
         }
 
         // Ensure `const fn` that are `stable` have one of `rustc_const_unstable` or
@@ -564,21 +564,21 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
         if self.tcx.features().staged_api
             && matches!(&i.kind, hir::ItemKind::Fn(sig, ..) if sig.header.is_const())
         {
-            self.check_missing_const_stability(i.hir_id, i.span);
+            self.check_missing_const_stability(i.hir_id(), i.span);
         }
 
         intravisit::walk_item(self, i)
     }
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
-        self.check_missing_stability(ti.hir_id, ti.span);
+        self.check_missing_stability(ti.hir_id(), ti.span);
         intravisit::walk_trait_item(self, ti);
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
-        let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent_item(ii.hir_id));
+        let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent_item(ii.hir_id()));
         if self.tcx.impl_trait_ref(impl_def_id).is_none() {
-            self.check_missing_stability(ii.hir_id, ii.span);
+            self.check_missing_stability(ii.hir_id(), ii.span);
         }
         intravisit::walk_impl_item(self, ii);
     }
@@ -594,12 +594,12 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
     }
 
     fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
-        self.check_missing_stability(i.hir_id, i.span);
+        self.check_missing_stability(i.hir_id(), i.span);
         intravisit::walk_foreign_item(self, i);
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        self.check_missing_stability(md.hir_id, md.span);
+        self.check_missing_stability(md.hir_id(), md.span);
     }
 
     // Note that we don't need to `check_missing_stability` for default generic parameters,
@@ -712,13 +712,12 @@ impl Visitor<'tcx> for Checker<'tcx> {
                     return;
                 }
 
-                let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                let cnum = match self.tcx.extern_mod_stmt_cnum(def_id) {
+                let cnum = match self.tcx.extern_mod_stmt_cnum(item.def_id) {
                     Some(cnum) => cnum,
                     None => return,
                 };
                 let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
-                self.tcx.check_stability(def_id, Some(item.hir_id), item.span);
+                self.tcx.check_stability(def_id, Some(item.hir_id()), item.span);
             }
 
             // For implementations of traits, check the stability of each item
@@ -744,7 +743,7 @@ impl Visitor<'tcx> for Checker<'tcx> {
                                 .map_or(item.span, |a| a.span);
                             self.tcx.struct_span_lint_hir(
                                 INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
-                                item.hir_id,
+                                item.hir_id(),
                                 span,
                                 |lint| lint
                                     .build("an `#[unstable]` annotation here has no effect")
@@ -775,15 +774,14 @@ impl Visitor<'tcx> for Checker<'tcx> {
             // There's no good place to insert stability check for non-Copy unions,
             // so semi-randomly perform it here in stability.rs
             hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
-                let def_id = self.tcx.hir().local_def_id(item.hir_id);
-                let ty = self.tcx.type_of(def_id);
+                let ty = self.tcx.type_of(item.def_id);
                 let (adt_def, substs) = match ty.kind() {
                     ty::Adt(adt_def, substs) => (adt_def, substs),
                     _ => bug!(),
                 };
 
                 // Non-`Copy` fields are unstable, except for `ManuallyDrop`.
-                let param_env = self.tcx.param_env(def_id);
+                let param_env = self.tcx.param_env(item.def_id);
                 for field in &adt_def.non_enum_variant().fields {
                     let field_ty = field.ty(self.tcx, substs);
                     if !field_ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs
index 4796d9a80b6..d5c287fb3bc 100644
--- a/compiler/rustc_plugin_impl/src/build.rs
+++ b/compiler/rustc_plugin_impl/src/build.rs
@@ -1,7 +1,7 @@
 //! Used by `rustc` when compiling a plugin crate.
 
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -10,14 +10,14 @@ use rustc_span::Span;
 
 struct RegistrarFinder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    registrars: Vec<(hir::HirId, Span)>,
+    registrars: Vec<(LocalDefId, Span)>,
 }
 
 impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::Fn(..) = item.kind {
             if self.tcx.sess.contains_name(&item.attrs, sym::plugin_registrar) {
-                self.registrars.push((item.hir_id, item.span));
+                self.registrars.push((item.def_id, item.span));
             }
         }
     }
@@ -43,8 +43,8 @@ fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
     match finder.registrars.len() {
         0 => None,
         1 => {
-            let (hir_id, _) = finder.registrars.pop().unwrap();
-            Some(tcx.hir().local_def_id(hir_id).to_def_id())
+            let (def_id, _) = finder.registrars.pop().unwrap();
+            Some(def_id.to_def_id())
         }
         _ => {
             let diagnostic = tcx.sess.diagnostic();
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 631dcb60594..890493fa853 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -454,11 +454,9 @@ impl EmbargoVisitor<'tcx> {
         let module_def_id = self.tcx.hir().local_def_id(reachable_mod);
         let module = self.tcx.hir().get_module(module_def_id).0;
         for item_id in module.item_ids {
-            let hir_id = item_id.id;
-            let item_def_id = self.tcx.hir().local_def_id(hir_id);
-            let def_kind = self.tcx.def_kind(item_def_id);
-            let vis = self.tcx.visibility(item_def_id);
-            self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
+            let def_kind = self.tcx.def_kind(item_id.def_id);
+            let vis = self.tcx.visibility(item_id.def_id);
+            self.update_macro_reachable_def(item_id.hir_id(), def_kind, vis, defining_mod);
         }
         if let Some(exports) = self.tcx.module_exports(module_def_id) {
             for export in exports {
@@ -588,14 +586,17 @@ impl EmbargoVisitor<'tcx> {
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
                 if let hir::ItemKind::Mod(m) = &item.kind {
-                    for item_id in m.item_ids {
-                        let item = self.tcx.hir().expect_item(item_id.id);
-                        let def_id = self.tcx.hir().local_def_id(item_id.id);
-                        if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id.to_def_id()) {
+                    for &item_id in m.item_ids {
+                        let item = self.tcx.hir().item(item_id);
+                        if !self.tcx.hygienic_eq(
+                            segment.ident,
+                            item.ident,
+                            item_id.def_id.to_def_id(),
+                        ) {
                             continue;
                         }
                         if let hir::ItemKind::Use(..) = item.kind {
-                            self.update(item.hir_id, Some(AccessLevel::Exported));
+                            self.update(item.hir_id(), Some(AccessLevel::Exported));
                         }
                     }
                 }
@@ -616,7 +617,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let inherited_item_level = match item.kind {
             hir::ItemKind::Impl { .. } => {
-                Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels)
+                Option::<AccessLevel>::of_impl(item.hir_id(), self.tcx, &self.access_levels)
             }
             // Foreign modules inherit level from parents.
             hir::ItemKind::ForeignMod { .. } => self.prev_level,
@@ -644,7 +645,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         };
 
         // Update level of the item itself.
-        let item_level = self.update(item.hir_id, inherited_item_level);
+        let item_level = self.update(item.hir_id(), inherited_item_level);
 
         // Update levels of nested things.
         match item.kind {
@@ -662,13 +663,13 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             hir::ItemKind::Impl(ref impl_) => {
                 for impl_item_ref in impl_.items {
                     if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
-                        self.update(impl_item_ref.id.hir_id, item_level);
+                        self.update(impl_item_ref.id.hir_id(), item_level);
                     }
                 }
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
-                    self.update(trait_item_ref.id.hir_id, item_level);
+                    self.update(trait_item_ref.id.hir_id(), item_level);
                 }
             }
             hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
@@ -684,7 +685,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
                     if foreign_item.vis.node.is_pub() {
-                        self.update(foreign_item.id.hir_id, item_level);
+                        self.update(foreign_item.id.hir_id(), item_level);
                     }
                 }
             }
@@ -727,7 +728,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     // reachable if they are returned via `impl Trait`, even from private functions.
                     let exist_level =
                         cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
-                    self.reach(item.hir_id, exist_level).generics().predicates().ty();
+                    self.reach(item.hir_id(), exist_level).generics().predicates().ty();
                 }
             }
             // Visit everything.
@@ -736,15 +737,15 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::TyAlias(..) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates().ty();
+                    self.reach(item.hir_id(), item_level).generics().predicates().ty();
                 }
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates();
+                    self.reach(item.hir_id(), item_level).generics().predicates();
 
                     for trait_item_ref in trait_item_refs {
-                        let mut reach = self.reach(trait_item_ref.id.hir_id, item_level);
+                        let mut reach = self.reach(trait_item_ref.id.hir_id(), item_level);
                         reach.generics().predicates();
 
                         if trait_item_ref.kind == AssocItemKind::Type
@@ -759,18 +760,18 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             }
             hir::ItemKind::TraitAlias(..) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates();
+                    self.reach(item.hir_id(), item_level).generics().predicates();
                 }
             }
             // Visit everything except for private impl items.
             hir::ItemKind::Impl(ref impl_) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
+                    self.reach(item.hir_id(), item_level).generics().predicates().ty().trait_ref();
 
                     for impl_item_ref in impl_.items {
-                        let impl_item_level = self.get(impl_item_ref.id.hir_id);
+                        let impl_item_level = self.get(impl_item_ref.id.hir_id());
                         if impl_item_level.is_some() {
-                            self.reach(impl_item_ref.id.hir_id, impl_item_level)
+                            self.reach(impl_item_ref.id.hir_id(), impl_item_level)
                                 .generics()
                                 .predicates()
                                 .ty();
@@ -782,7 +783,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             // Visit everything, but enum variants have their own levels.
             hir::ItemKind::Enum(ref def, _) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates();
+                    self.reach(item.hir_id(), item_level).generics().predicates();
                 }
                 for variant in def.variants {
                     let variant_level = self.get(variant.id);
@@ -792,16 +793,16 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
                         }
                         // Corner case: if the variant is reachable, but its
                         // enum is not, make the enum reachable as well.
-                        self.update(item.hir_id, variant_level);
+                        self.update(item.hir_id(), variant_level);
                     }
                 }
             }
             // Visit everything, but foreign items have their own levels.
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    let foreign_item_level = self.get(foreign_item.id.hir_id);
+                    let foreign_item_level = self.get(foreign_item.id.hir_id());
                     if foreign_item_level.is_some() {
-                        self.reach(foreign_item.id.hir_id, foreign_item_level)
+                        self.reach(foreign_item.id.hir_id(), foreign_item_level)
                             .generics()
                             .predicates()
                             .ty();
@@ -811,7 +812,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             // Visit everything except for private fields.
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
                 if item_level.is_some() {
-                    self.reach(item.hir_id, item_level).generics().predicates();
+                    self.reach(item.hir_id(), item_level).generics().predicates();
                     for field in struct_def.fields() {
                         let field_level = self.get(field.hir_id);
                         if field_level.is_some() {
@@ -866,14 +867,12 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             // `#[macro_export]`-ed `macro_rules!` are `Public` since they
             // ignore their containing path to always appear at the crate root.
             if md.ast.macro_rules {
-                self.update(md.hir_id, Some(AccessLevel::Public));
+                self.update(md.hir_id(), Some(AccessLevel::Public));
             }
             return;
         }
 
-        let macro_module_def_id =
-            ty::DefIdTree::parent(self.tcx, self.tcx.hir().local_def_id(md.hir_id).to_def_id())
-                .unwrap();
+        let macro_module_def_id = ty::DefIdTree::parent(self.tcx, md.def_id.to_def_id()).unwrap();
         let hir_id = macro_module_def_id
             .as_local()
             .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
@@ -883,7 +882,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
             _ => return,
         };
         let level = if md.vis.node.is_pub() { self.get(module_id) } else { None };
-        let new_level = self.update(md.hir_id, level);
+        let new_level = self.update(md.hir_id(), level);
         if new_level.is_none() {
             return;
         }
@@ -1037,7 +1036,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let orig_current_item = self.current_item.replace(item.hir_id);
+        let orig_current_item = self.current_item.replace(item.hir_id());
         intravisit::walk_item(self, item);
         self.current_item = orig_current_item;
     }
@@ -1322,8 +1321,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
 
     // Check types in item interfaces.
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let orig_current_item =
-            mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.hir_id));
+        let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
         let old_maybe_typeck_results = self.maybe_typeck_results.take();
         intravisit::walk_item(self, item);
         self.maybe_typeck_results = old_maybe_typeck_results;
@@ -1463,7 +1461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
             hir::ItemKind::ForeignMod { .. } => {}
 
             hir::ItemKind::Trait(.., ref bounds, _) => {
-                if !self.trait_is_public(item.hir_id) {
+                if !self.trait_is_public(item.hir_id()) {
                     return;
                 }
 
@@ -1526,7 +1524,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         match impl_item.kind {
                             hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
-                                self.access_levels.is_reachable(impl_item_ref.id.hir_id)
+                                self.access_levels.is_reachable(impl_item_ref.id.hir_id())
                             }
                             hir::ImplItemKind::TyAlias(_) => false,
                         }
@@ -1546,8 +1544,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 match impl_item.kind {
                                     hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
-                                        if self
-                                            .item_is_public(&impl_item.hir_id, &impl_item.vis) =>
+                                        if self.item_is_public(
+                                            &impl_item.hir_id(),
+                                            &impl_item.vis,
+                                        ) =>
                                     {
                                         intravisit::walk_impl_item(self, impl_item)
                                     }
@@ -1588,7 +1588,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
                     for impl_item_ref in impl_.items {
-                        if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) {
+                        if self.item_is_public(&impl_item_ref.id.hir_id(), &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
                                 AssocItemKind::Const => {
@@ -1615,7 +1615,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
             hir::ItemKind::TyAlias(..) => return,
 
             // Not at all public, so we don't care.
-            _ if !self.item_is_public(&item.hir_id, &item.vis) => {
+            _ if !self.item_is_public(&item.hir_id(), &item.vis) => {
                 return;
             }
 
@@ -1651,7 +1651,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
-        if self.access_levels.is_reachable(item.hir_id) {
+        if self.access_levels.is_reachable(item.hir_id()) {
             intravisit::walk_foreign_item(self, item)
         }
     }
@@ -1926,7 +1926,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let tcx = self.tcx;
-        let item_visibility = tcx.visibility(tcx.hir().local_def_id(item.hir_id).to_def_id());
+        let item_visibility = tcx.visibility(item.def_id);
 
         match item.kind {
             // Crates are always public.
@@ -1942,34 +1942,34 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::TyAlias(..) => {
-                self.check(item.hir_id, item_visibility).generics().predicates().ty();
+                self.check(item.hir_id(), item_visibility).generics().predicates().ty();
             }
             hir::ItemKind::OpaqueTy(..) => {
                 // `ty()` for opaque types is the underlying type,
                 // it's not a part of interface, so we skip it.
-                self.check(item.hir_id, item_visibility).generics().bounds();
+                self.check(item.hir_id(), item_visibility).generics().bounds();
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
-                self.check(item.hir_id, item_visibility).generics().predicates();
+                self.check(item.hir_id(), item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
                     self.check_assoc_item(
-                        trait_item_ref.id.hir_id,
+                        trait_item_ref.id.hir_id(),
                         trait_item_ref.kind,
                         trait_item_ref.defaultness,
                         item_visibility,
                     );
 
                     if let AssocItemKind::Type = trait_item_ref.kind {
-                        self.check(trait_item_ref.id.hir_id, item_visibility).bounds();
+                        self.check(trait_item_ref.id.hir_id(), item_visibility).bounds();
                     }
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
-                self.check(item.hir_id, item_visibility).generics().predicates();
+                self.check(item.hir_id(), item_visibility).generics().predicates();
             }
             hir::ItemKind::Enum(ref def, _) => {
-                self.check(item.hir_id, item_visibility).generics().predicates();
+                self.check(item.hir_id(), item_visibility).generics().predicates();
 
                 for variant in def.variants {
                     for field in variant.data.fields() {
@@ -1980,13 +1980,13 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             // Subitems of foreign modules have their own publicity.
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    let vis = tcx.visibility(tcx.hir().local_def_id(foreign_item.id.hir_id));
-                    self.check(foreign_item.id.hir_id, vis).generics().predicates().ty();
+                    let vis = tcx.visibility(foreign_item.id.def_id);
+                    self.check(foreign_item.id.hir_id(), vis).generics().predicates().ty();
                 }
             }
             // Subitems of structs and unions have their own publicity.
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                self.check(item.hir_id, item_visibility).generics().predicates();
+                self.check(item.hir_id(), item_visibility).generics().predicates();
 
                 for field in struct_def.fields() {
                     let field_visibility = tcx.visibility(tcx.hir().local_def_id(field.hir_id));
@@ -1998,20 +1998,16 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
             hir::ItemKind::Impl(ref impl_) => {
-                let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
-                self.check(item.hir_id, impl_vis).generics().predicates();
+                let impl_vis = ty::Visibility::of_impl(item.hir_id(), tcx, &Default::default());
+                self.check(item.hir_id(), impl_vis).generics().predicates();
                 for impl_item_ref in impl_.items {
                     let impl_item_vis = if impl_.of_trait.is_none() {
-                        min(
-                            tcx.visibility(tcx.hir().local_def_id(impl_item_ref.id.hir_id)),
-                            impl_vis,
-                            tcx,
-                        )
+                        min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx)
                     } else {
                         impl_vis
                     };
                     self.check_assoc_item(
-                        impl_item_ref.id.hir_id,
+                        impl_item_ref.id.hir_id(),
                         impl_item_ref.kind,
                         impl_item_ref.defaultness,
                         impl_item_vis,
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 2610ce83e4d..4242324b968 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -385,6 +385,7 @@ where
 /// It returns the shard index and a lock guard to the shard,
 /// which will be used if the query is not in the cache and we need
 /// to compute it.
+#[inline]
 pub fn try_get_cached<'a, CTX, C, R, OnHit>(
     tcx: CTX,
     cache: &'a QueryCacheStore<C>,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d2a693a5688..6457c6cee57 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1105,7 +1105,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         }
 
         if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items {
-            for assoc_item in &items[..] {
+            for assoc_item in items {
                 if assoc_item.ident == ident {
                     return Some(match &assoc_item.kind {
                         ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 0bab33976b2..c0e4a1bdf07 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -587,7 +587,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
                 //                 ^                  ^ this gets resolved in the scope of
                 //                                      the opaque_ty generics
-                let opaque_ty = self.tcx.hir().expect_item(item_id.id);
+                let opaque_ty = self.tcx.hir().item(item_id);
                 let (generics, bounds) = match opaque_ty.kind {
                     // Named opaque `impl Trait` types are reached via `TyKind::Path`.
                     // This arm is for `impl Trait` in the types of statics, constants and locals.
@@ -632,20 +632,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 // Ensure that the parent of the def is an item, not HRTB
                                 let parent_id = self.tcx.hir().get_parent_node(hir_id);
-                                let parent_impl_id = hir::ImplItemId { hir_id: parent_id };
-                                let parent_trait_id = hir::TraitItemId { hir_id: parent_id };
-                                let krate = self.tcx.hir().krate();
-
-                                if !(krate.items.contains_key(&parent_id)
-                                    || krate.impl_items.contains_key(&parent_impl_id)
-                                    || krate.trait_items.contains_key(&parent_trait_id))
+                                let parent_is_item = if let Some(parent_def_id) =
+                                    parent_id.as_owner()
                                 {
+                                    let parent_item_id = hir::ItemId { def_id: parent_def_id };
+                                    let parent_impl_id = hir::ImplItemId { def_id: parent_def_id };
+                                    let parent_trait_id =
+                                        hir::TraitItemId { def_id: parent_def_id };
+                                    let parent_foreign_id =
+                                        hir::ForeignItemId { def_id: parent_def_id };
+                                    let krate = self.tcx.hir().krate();
+
+                                    krate.items.contains_key(&parent_item_id)
+                                        || krate.impl_items.contains_key(&parent_impl_id)
+                                        || krate.trait_items.contains_key(&parent_trait_id)
+                                        || krate.foreign_items.contains_key(&parent_foreign_id)
+                                } else {
+                                    false
+                                };
+
+                                if !parent_is_item {
                                     struct_span_err!(
                                         self.tcx.sess,
                                         lifetime.span,
                                         E0657,
                                         "`impl Trait` can only capture lifetimes \
-                                         bound at the fn or impl level"
+                                             bound at the fn or impl level"
                                     )
                                     .emit();
                                     self.uninsert_lifetime_on_error(lifetime, def.unwrap());
@@ -738,7 +750,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 self.missing_named_lifetime_spots.push((&trait_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(trait_item.hir_id)),
+                    Some(tcx.hir().get_parent_item(trait_item.hir_id())),
                     &sig.decl,
                     &trait_item.generics,
                     |this| intravisit::walk_trait_item(this, trait_item),
@@ -800,7 +812,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 self.missing_named_lifetime_spots.push((&impl_item.generics).into());
                 let tcx = self.tcx;
                 self.visit_early_late(
-                    Some(tcx.hir().get_parent_item(impl_item.hir_id)),
+                    Some(tcx.hir().get_parent_item(impl_item.hir_id())),
                     &sig.decl,
                     &impl_item.generics,
                     |this| intravisit::walk_impl_item(this, impl_item),
@@ -1255,7 +1267,7 @@ fn compute_object_lifetime_defaults(tcx: TyCtxt<'_>) -> HirIdMap<Vec<ObjectLifet
                     tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
                 }
 
-                map.insert(item.hir_id, result);
+                map.insert(item.hir_id(), result);
             }
             _ => {}
         }
@@ -2111,7 +2123,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
                     assoc_item_kind =
-                        trait_items.iter().find(|ti| ti.id.hir_id == parent).map(|ti| ti.kind);
+                        trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
                 }
                 match *m {
                     hir::TraitFn::Required(_) => None,
@@ -2125,7 +2137,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 {
                     impl_self = Some(self_ty);
                     assoc_item_kind =
-                        items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind);
+                        items.iter().find(|ii| ii.id.hir_id() == parent).map(|ii| ii.kind);
                 }
                 Some(body)
             }
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 2834e7b6322..625d7c83120 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -373,14 +373,14 @@ impl<'tcx> DumpVisitor<'tcx> {
         body: hir::BodyId,
     ) {
         let map = &self.tcx.hir();
-        self.nest_typeck_results(map.local_def_id(item.hir_id), |v| {
+        self.nest_typeck_results(item.def_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(body.params, &fn_data.qualname);
-                v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id);
+                v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id());
 
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item, 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 {
@@ -401,10 +401,10 @@ impl<'tcx> DumpVisitor<'tcx> {
         typ: &'tcx hir::Ty<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
     ) {
-        self.nest_typeck_results(self.tcx.hir().local_def_id(item.hir_id), |v| {
+        self.nest_typeck_results(item.def_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, item.hir_id), var_data);
+                v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.hir_id()), var_data);
             }
             v.visit_ty(&typ);
             v.visit_expr(expr);
@@ -465,10 +465,7 @@ impl<'tcx> DumpVisitor<'tcx> {
     ) {
         debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
-        let qualname = format!(
-            "::{}",
-            self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
-        );
+        let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
 
         let kind = match item.kind {
             hir::ItemKind::Struct(_, _) => DefKind::Struct,
@@ -500,10 +497,10 @@ impl<'tcx> DumpVisitor<'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, item.hir_id),
+                &access_from!(self.save_ctxt, item, item.hir_id()),
                 Def {
                     kind,
-                    id: id_from_hir_id(item.hir_id, &self.save_ctxt),
+                    id: id_from_def_id(item.def_id.to_def_id()),
                     span,
                     name,
                     qualname: qualname.clone(),
@@ -518,13 +515,13 @@ impl<'tcx> DumpVisitor<'tcx> {
             );
         }
 
-        self.nest_typeck_results(self.tcx.hir().local_def_id(item.hir_id), |v| {
+        self.nest_typeck_results(item.def_id, |v| {
             for field in def.fields() {
-                v.process_struct_field_def(field, item.hir_id);
+                v.process_struct_field_def(field, item.hir_id());
                 v.visit_ty(&field.ty);
             }
 
-            v.process_generic_params(ty_params, &qualname, item.hir_id);
+            v.process_generic_params(ty_params, &qualname, item.hir_id());
         });
     }
 
@@ -541,7 +538,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         };
         down_cast_data!(enum_data, DefData, item.span);
 
-        let access = access_from!(self.save_ctxt, item, item.hir_id);
+        let access = access_from!(self.save_ctxt, item, item.hir_id());
 
         for variant in enum_definition.variants {
             let name = variant.ident.name.to_string();
@@ -556,7 +553,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
                         let id = id_from_hir_id(variant.id, &self.save_ctxt);
-                        let parent = Some(id_from_hir_id(item.hir_id, &self.save_ctxt));
+                        let parent = Some(id_from_def_id(item.def_id.to_def_id()));
 
                         self.dumper.dump_def(
                             &access,
@@ -596,7 +593,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
                         let id = id_from_hir_id(variant.id, &self.save_ctxt);
-                        let parent = Some(id_from_hir_id(item.hir_id, &self.save_ctxt));
+                        let parent = Some(id_from_def_id(item.def_id.to_def_id()));
 
                         self.dumper.dump_def(
                             &access,
@@ -627,7 +624,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 self.visit_ty(field.ty);
             }
         }
-        self.process_generic_params(ty_params, &enum_data.qualname, item.hir_id);
+        self.process_generic_params(ty_params, &enum_data.qualname, item.hir_id());
         self.dumper.dump_def(&access, enum_data);
     }
 
@@ -644,17 +641,14 @@ impl<'tcx> DumpVisitor<'tcx> {
         }
 
         let map = &self.tcx.hir();
-        self.nest_typeck_results(map.local_def_id(item.hir_id), |v| {
+        self.nest_typeck_results(item.def_id, |v| {
             v.visit_ty(&impl_.self_ty);
             if let Some(trait_ref) = &impl_.of_trait {
                 v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
             }
-            v.process_generic_params(&impl_.generics, "", item.hir_id);
+            v.process_generic_params(&impl_.generics, "", item.hir_id());
             for impl_item in impl_.items {
-                v.process_impl_item(
-                    map.impl_item(impl_item.id),
-                    map.local_def_id(item.hir_id).to_def_id(),
-                );
+                v.process_impl_item(map.impl_item(impl_item.id), item.def_id.to_def_id());
             }
         });
     }
@@ -667,10 +661,7 @@ impl<'tcx> DumpVisitor<'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(item.hir_id).to_def_id())
-        );
+        let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
         let mut val = name.clone();
         if !generics.params.is_empty() {
             val.push_str(&generic_params_to_string(generics.params));
@@ -680,12 +671,12 @@ impl<'tcx> DumpVisitor<'tcx> {
             val.push_str(&bounds_to_string(trait_refs));
         }
         if !self.span.filter_generated(item.ident.span) {
-            let id = id_from_hir_id(item.hir_id, &self.save_ctxt);
+            let id = id_from_def_id(item.def_id.to_def_id());
             let span = self.span_from_span(item.ident.span);
             let children =
-                methods.iter().map(|i| id_from_hir_id(i.id.hir_id, &self.save_ctxt)).collect();
+                methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect();
             self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item, item.hir_id),
+                &access_from!(self.save_ctxt, item, item.hir_id()),
                 Def {
                     kind: DefKind::Trait,
                     id,
@@ -729,20 +720,17 @@ impl<'tcx> DumpVisitor<'tcx> {
                         kind: RelationKind::SuperTrait,
                         span,
                         from: id_from_def_id(id),
-                        to: id_from_hir_id(item.hir_id, &self.save_ctxt),
+                        to: id_from_def_id(item.def_id.to_def_id()),
                     });
                 }
             }
         }
 
         // walk generics and methods
-        self.process_generic_params(generics, &qualname, item.hir_id);
+        self.process_generic_params(generics, &qualname, item.hir_id());
         for method in methods {
             let map = &self.tcx.hir();
-            self.process_trait_item(
-                map.trait_item(method.id),
-                map.local_def_id(item.hir_id).to_def_id(),
-            )
+            self.process_trait_item(map.trait_item(method.id), item.def_id.to_def_id())
         }
     }
 
@@ -750,7 +738,7 @@ impl<'tcx> DumpVisitor<'tcx> {
     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);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.hir_id), mod_data);
+            self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.hir_id()), mod_data);
         }
     }
 
@@ -1011,7 +999,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 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.hir_id,
+                    trait_item.hir_id(),
                     trait_item.ident,
                     &ty,
                     body,
@@ -1027,7 +1015,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 self.process_method(
                     sig,
                     body,
-                    trait_item.hir_id,
+                    trait_item.hir_id(),
                     trait_item.ident,
                     &trait_item.generics,
                     &respan,
@@ -1037,15 +1025,12 @@ impl<'tcx> DumpVisitor<'tcx> {
             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(trait_item.hir_id).to_def_id())
-                );
+                let qualname =
+                    format!("::{}", self.tcx.def_path_str(trait_item.def_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_hir_id(trait_item.hir_id, &self.save_ctxt);
+                    let id = id_from_def_id(trait_item.def_id.to_def_id());
 
                     self.dumper.dump_def(
                         &Access { public: true, reachable: true },
@@ -1061,7 +1046,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                             decl_id: None,
                             docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
                             sig: sig::assoc_type_signature(
-                                trait_item.hir_id,
+                                trait_item.hir_id(),
                                 trait_item.ident,
                                 Some(bounds),
                                 default_ty.as_ref().map(|ty| &**ty),
@@ -1088,7 +1073,7 @@ impl<'tcx> DumpVisitor<'tcx> {
             hir::ImplItemKind::Const(ref ty, body) => {
                 let body = self.tcx.hir().body(body);
                 self.process_assoc_const(
-                    impl_item.hir_id,
+                    impl_item.hir_id(),
                     impl_item.ident,
                     &ty,
                     Some(&body.value),
@@ -1101,7 +1086,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 self.process_method(
                     sig,
                     Some(body),
-                    impl_item.hir_id,
+                    impl_item.hir_id(),
                     impl_item.ident,
                     &impl_item.generics,
                     &impl_item.vis,
@@ -1130,7 +1115,7 @@ impl<'tcx> DumpVisitor<'tcx> {
             .module
             .item_ids
             .iter()
-            .map(|i| id_from_hir_id(i.id, &self.save_ctxt))
+            .map(|i| id_from_def_id(i.def_id.to_def_id()))
             .collect();
         let span = self.span_from_span(krate.item.span);
 
@@ -1179,16 +1164,11 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
             hir::ItemKind::Use(path, hir::UseKind::Single) => {
                 let sub_span = path.segments.last().unwrap().ident.span;
                 if !self.span.filter_generated(sub_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 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);
+                    let parent =
+                        self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
                     self.dumper.import(
                         &access,
                         Import {
@@ -1206,23 +1186,17 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
             }
             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(item.hir_id);
-                let names = self.tcx.names_imported_by_glob_use(def_id);
+                let names = self.tcx.names_imported_by_glob_use(item.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_star(item.span) {
                     if !self.span.filter_generated(item.span) {
-                        let access = access_from!(self.save_ctxt, item, item.hir_id);
+                        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);
+                        let parent =
+                            self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
                         self.dumper.import(
                             &access,
                             Import {
@@ -1243,13 +1217,8 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
                 let name_span = item.ident.span;
                 if !self.span.filter_generated(name_span) {
                     let span = self.span_from_span(name_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);
+                    let parent =
+                        self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
                     self.dumper.import(
                         &Access { public: false, reachable: false },
                         Import {
@@ -1286,20 +1255,17 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
             }
             hir::ItemKind::Mod(ref m) => {
                 self.process_mod(item);
-                intravisit::walk_mod(self, m, item.hir_id);
+                intravisit::walk_mod(self, m, item.hir_id());
             }
             hir::ItemKind::TyAlias(ty, ref generics) => {
-                let qualname = format!(
-                    "::{}",
-                    self.tcx.def_path_str(self.tcx.hir().local_def_id(item.hir_id).to_def_id())
-                );
+                let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
                 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_hir_id(item.hir_id, &self.save_ctxt);
+                    let id = id_from_def_id(item.def_id.to_def_id());
 
                     self.dumper.dump_def(
-                        &access_from!(self.save_ctxt, item, item.hir_id),
+                        &access_from!(self.save_ctxt, item, item.hir_id()),
                         Def {
                             kind: DefKind::Type,
                             id,
@@ -1318,7 +1284,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
                 }
 
                 self.visit_ty(ty);
-                self.process_generic_params(generics, &qualname, item.hir_id);
+                self.process_generic_params(generics, &qualname, item.hir_id());
             }
             _ => intravisit::walk_item(self, item),
         }
@@ -1382,10 +1348,8 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
                 });
             }
             hir::TyKind::OpaqueDef(item_id, _) => {
-                let item = self.tcx.hir().item(item_id.id);
-                self.nest_typeck_results(self.tcx.hir().local_def_id(item_id.id), |v| {
-                    v.visit_item(item)
-                });
+                let item = self.tcx.hir().item(item_id);
+                self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item));
             }
             _ => intravisit::walk_ty(self, t),
         }
@@ -1485,14 +1449,14 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
     }
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
-        let access = access_from!(self.save_ctxt, item, item.hir_id);
+        let access = access_from!(self.save_ctxt, item, item.hir_id());
 
         match item.kind {
             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.hir_id);
+                    self.process_generic_params(generics, &fn_data.qualname, item.hir_id());
                     self.dumper.dump_def(&access, fn_data);
                 }
 
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 129123349a0..b3f281bcabc 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -137,7 +137,7 @@ impl<'tcx> SaveContext<'tcx> {
     }
 
     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 def_id = item.def_id.to_def_id();
         let qualname = format!("::{}", self.tcx.def_path_str(def_id));
         match item.kind {
             hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
@@ -156,7 +156,7 @@ impl<'tcx> SaveContext<'tcx> {
                             unsafety: hir::Unsafety::Unsafe,
                             // functions in extern block cannot be const
                             constness: hir::Constness::NotConst,
-                            abi: self.tcx.hir().get_foreign_abi(item.hir_id),
+                            abi: self.tcx.hir().get_foreign_abi(item.hir_id()),
                             // functions in extern block cannot be async
                             asyncness: hir::IsAsync::NotAsync,
                         },
@@ -201,7 +201,7 @@ impl<'tcx> SaveContext<'tcx> {
     }
 
     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();
+        let def_id = item.def_id.to_def_id();
         match item.kind {
             hir::ItemKind::Fn(ref sig, ref generics, _) => {
                 let qualname = format!("::{}", self.tcx.def_path_str(def_id));
@@ -290,7 +290,11 @@ impl<'tcx> SaveContext<'tcx> {
                     span: self.span_from_span(item.ident.span),
                     value: filename.to_string(),
                     parent: None,
-                    children: m.item_ids.iter().map(|i| id_from_hir_id(i.id, self)).collect(),
+                    children: m
+                        .item_ids
+                        .iter()
+                        .map(|i| id_from_def_id(i.def_id.to_def_id()))
+                        .collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
                     sig: sig::item_signature(item, self),
@@ -354,7 +358,7 @@ impl<'tcx> SaveContext<'tcx> {
                                 parent: None,
                                 children: items
                                     .iter()
-                                    .map(|i| id_from_hir_id(i.id.hir_id, self))
+                                    .map(|i| id_from_def_id(i.id.def_id.to_def_id()))
                                     .collect(),
                                 docs: String::new(),
                                 sig: None,
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index 8ada7e34fe8..33db189af37 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -317,8 +317,8 @@ impl<'hir> Sig for hir::Ty<'hir> {
                 Ok(replace_text(nested_ty, text))
             }
             hir::TyKind::OpaqueDef(item_id, _) => {
-                let item = scx.tcx.hir().item(item_id.id);
-                item.make(offset, Some(item_id.id), scx)
+                let item = scx.tcx.hir().item(item_id);
+                item.make(offset, Some(item_id.hir_id()), scx)
             }
             hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
         }
@@ -327,7 +327,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
 
 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);
+        let id = Some(self.hir_id());
 
         match self.kind {
             hir::ItemKind::Static(ref ty, m, ref body) => {
@@ -337,7 +337,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 }
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_hir_id(self.hir_id, scx),
+                    id: id_from_def_id(self.def_id.to_def_id()),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -359,7 +359,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 let mut text = "const ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_hir_id(self.hir_id, scx),
+                    id: id_from_def_id(self.def_id.to_def_id()),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -391,7 +391,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 text.push_str("fn ");
 
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
 
                 sig.text.push('(');
                 for i in decl.inputs {
@@ -420,7 +420,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 let mut text = "mod ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_hir_id(self.hir_id, scx),
+                    id: id_from_def_id(self.def_id.to_def_id()),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -433,7 +433,7 @@ impl<'hir> Sig for hir::Item<'hir> {
             hir::ItemKind::TyAlias(ref ty, ref generics) => {
                 let text = "type ".to_owned();
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
 
                 sig.text.push_str(" = ");
                 let ty = ty.make(offset + sig.text.len(), id, scx)?;
@@ -445,21 +445,21 @@ impl<'hir> Sig for hir::Item<'hir> {
             hir::ItemKind::Enum(_, ref generics) => {
                 let text = "enum ".to_owned();
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
             hir::ItemKind::Struct(_, ref generics) => {
                 let text = "struct ".to_owned();
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
             hir::ItemKind::Union(_, ref generics) => {
                 let text = "union ".to_owned();
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
@@ -475,7 +475,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 }
                 text.push_str("trait ");
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
 
                 if !bounds.is_empty() {
                     sig.text.push_str(": ");
@@ -490,7 +490,7 @@ impl<'hir> Sig for hir::Item<'hir> {
                 let mut text = String::new();
                 text.push_str("trait ");
                 let mut sig =
-                    name_and_generics(text, offset, generics, self.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
 
                 if !bounds.is_empty() {
                     sig.text.push_str(" = ");
@@ -736,14 +736,14 @@ impl<'hir> Sig for hir::Variant<'hir> {
 
 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);
+        let id = Some(self.hir_id());
         match self.kind {
             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.hir_id, self.ident, scx)?;
+                    name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
 
                 sig.text.push('(');
                 for i in decl.inputs {
@@ -774,7 +774,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> {
                 }
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_hir_id(self.hir_id, scx),
+                    id: id_from_def_id(self.def_id.to_def_id()),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
@@ -790,7 +790,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> {
                 let mut text = "type ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
-                    id: id_from_hir_id(self.hir_id, scx),
+                    id: id_from_def_id(self.def_id.to_def_id()),
                     start: offset + text.len(),
                     end: offset + text.len() + name.len(),
                 }];
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 210dbb0ee99..4533b37f10b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1350,7 +1350,7 @@ pub fn parse_error_format(
     error_format
 }
 
-fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
+pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
     let edition = match matches.opt_str("edition") {
         Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
             early_error(
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index b24ede9c53a..70e9526f626 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -227,6 +227,8 @@ pub struct LocalDefId {
     pub local_def_index: DefIndex,
 }
 
+pub const CRATE_DEF_ID: LocalDefId = LocalDefId { local_def_index: CRATE_DEF_INDEX };
+
 impl Idx for LocalDefId {
     #[inline]
     fn new(idx: usize) -> Self {
@@ -268,6 +270,8 @@ impl<D: Decoder> Decodable<D> for LocalDefId {
     }
 }
 
+rustc_data_structures::define_id_collections!(LocalDefIdMap, LocalDefIdSet, LocalDefId);
+
 impl<CTX: HashStableContext> HashStable<CTX> for DefId {
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
         hcx.hash_def_id(*self, hasher)
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 298c995b166..b7eb6d5b379 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -778,16 +778,35 @@ impl SourceMap {
         self.span_until_char(sp, '{')
     }
 
-    /// Returns a new span representing just the start point of this span.
+    /// Returns a new span representing just the first character of the given span.
     pub fn start_point(&self, sp: Span) -> Span {
-        let pos = sp.lo().0;
-        let width = self.find_width_of_character_at_span(sp, false);
-        let corrected_start_position = pos.checked_add(width).unwrap_or(pos);
-        let end_point = BytePos(cmp::max(corrected_start_position, sp.lo().0));
-        sp.with_hi(end_point)
+        let width = {
+            let sp = sp.data();
+            let local_begin = self.lookup_byte_offset(sp.lo);
+            let start_index = local_begin.pos.to_usize();
+            let src = local_begin.sf.external_src.borrow();
+
+            let snippet = if let Some(ref src) = local_begin.sf.src {
+                Some(&src[start_index..])
+            } else if let Some(src) = src.get_source() {
+                Some(&src[start_index..])
+            } else {
+                None
+            };
+
+            match snippet {
+                None => 1,
+                Some(snippet) => match snippet.chars().next() {
+                    None => 1,
+                    Some(c) => c.len_utf8(),
+                },
+            }
+        };
+
+        sp.with_hi(BytePos(sp.lo().0 + width as u32))
     }
 
-    /// Returns a new span representing just the end point of this span.
+    /// Returns a new span representing just the last character of this span.
     pub fn end_point(&self, sp: Span) -> Span {
         let pos = sp.hi().0;
 
@@ -816,7 +835,8 @@ impl SourceMap {
         Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt())
     }
 
-    /// Finds the width of a character, either before or after the provided span.
+    /// Finds the width of the character, either before or after the end of provided span,
+    /// depending on the `forwards` parameter.
     fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
         let sp = sp.data();
         if sp.lo == sp.hi {
@@ -863,11 +883,9 @@ impl SourceMap {
         // We need to extend the snippet to the end of the src rather than to end_index so when
         // searching forwards for boundaries we've got somewhere to search.
         let snippet = if let Some(ref src) = local_begin.sf.src {
-            let len = src.len();
-            &src[start_index..len]
+            &src[start_index..]
         } else if let Some(src) = src.get_source() {
-            let len = src.len();
-            &src[start_index..len]
+            &src[start_index..]
         } else {
             return 1;
         };
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index 8c5e438a728..bfe9c4d6de3 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -5,6 +5,7 @@
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc_hir as hir;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
@@ -31,9 +32,8 @@ struct SymbolNamesTest<'tcx> {
 }
 
 impl SymbolNamesTest<'tcx> {
-    fn process_attrs(&mut self, hir_id: hir::HirId) {
+    fn process_attrs(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx;
-        let def_id = tcx.hir().local_def_id(hir_id);
         for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
             if tcx.sess.check_name(attr, SYMBOL_NAME) {
                 let def_id = def_id.to_def_id();
@@ -61,18 +61,18 @@ impl SymbolNamesTest<'tcx> {
 
 impl hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.process_attrs(item.hir_id);
+        self.process_attrs(item.def_id);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        self.process_attrs(trait_item.hir_id);
+        self.process_attrs(trait_item.def_id);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        self.process_attrs(impl_item.hir_id);
+        self.process_attrs(impl_item.def_id);
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
-        self.process_attrs(foreign_item.hir_id);
+        self.process_attrs(foreign_item.def_id);
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0e55c4ec0b7..5b14795f545 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -783,9 +783,11 @@ supported_targets! {
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
     ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
+    ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
     ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
     ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
     ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
+    ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
 
     ("aarch64-unknown-none", aarch64_unknown_none),
     ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
@@ -1492,7 +1494,7 @@ impl Target {
             } );
             ($key_name:ident = $json_name:expr, optional) => ( {
                 let name = $json_name;
-                if let Some(o) = obj.find(&name[..]) {
+                if let Some(o) = obj.find(name) {
                     base.$key_name = o
                         .as_string()
                         .map(|s| s.to_string() );
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
new file mode 100644
index 00000000000..e5fbd09297f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs
@@ -0,0 +1,19 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "riscv32-unknown-linux-musl".to_string(),
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        arch: "riscv32".to_string(),
+        options: TargetOptions {
+            unsupported_abis: super::riscv_base::unsupported_abis(),
+            code_model: Some(CodeModel::Medium),
+            cpu: "generic-rv32".to_string(),
+            features: "+m,+a,+f,+d,+c".to_string(),
+            llvm_abiname: "ilp32d".to_string(),
+            max_atomic_width: Some(32),
+            ..super::linux_musl_base::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
new file mode 100644
index 00000000000..0232b15e8c2
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs
@@ -0,0 +1,19 @@
+use crate::spec::{CodeModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "riscv64-unknown-linux-musl".to_string(),
+        pointer_width: 64,
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
+        arch: "riscv64".to_string(),
+        options: TargetOptions {
+            unsupported_abis: super::riscv_base::unsupported_abis(),
+            code_model: Some(CodeModel::Medium),
+            cpu: "generic-rv64".to_string(),
+            features: "+m,+a,+f,+d,+c".to_string(),
+            llvm_abiname: "lp64d".to_string(),
+            max_atomic_width: Some(64),
+            ..super::linux_musl_base::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 77aa4413409..76d27c29226 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -82,7 +82,7 @@ fn associated_item_from_trait_item_ref(
     parent_def_id: LocalDefId,
     trait_item_ref: &hir::TraitItemRef,
 ) -> ty::AssocItem {
-    let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
+    let def_id = trait_item_ref.id.def_id;
     let (kind, has_self) = match trait_item_ref.kind {
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
@@ -105,7 +105,7 @@ fn associated_item_from_impl_item_ref(
     parent_def_id: LocalDefId,
     impl_item_ref: &hir::ImplItemRef<'_>,
 ) -> ty::AssocItem {
-    let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
+    let def_id = impl_item_ref.id.def_id;
     let (kind, has_self) = match impl_item_ref.kind {
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
@@ -130,7 +130,9 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     let parent_item = tcx.hir().expect_item(parent_id);
     match parent_item.kind {
         hir::ItemKind::Impl(ref impl_) => {
-            if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.hir_id == id) {
+            if let Some(impl_item_ref) =
+                impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id)
+            {
                 let assoc_item =
                     associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
                 debug_assert_eq!(assoc_item.def_id, def_id);
@@ -139,7 +141,9 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
         }
 
         hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
+            if let Some(trait_item_ref) =
+                trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id)
+            {
                 let assoc_item =
                     associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref);
                 debug_assert_eq!(assoc_item.def_id, def_id);
@@ -196,17 +200,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     let item = tcx.hir().expect_item(id);
     match item.kind {
         hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
-            trait_item_refs
-                .iter()
-                .map(|trait_item_ref| trait_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
+            trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()),
         ),
         hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
-            impl_
-                .items
-                .iter()
-                .map(|impl_item_ref| impl_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id).to_def_id()),
+            impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()),
         ),
         hir::ItemKind::TraitAlias(..) => &[],
         _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index 545c30169b9..b5404c3a15c 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -237,7 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
         if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
-            match &bound.trait_ref.path.segments[..] {
+            match bound.trait_ref.path.segments {
                 // FIXME: `trait_ref.path.span` can point to a full path with multiple
                 // segments, even though `trait_ref.path.segments` is of length `1`. Work
                 // around that bug here, even though it should be fixed elsewhere.
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 67e37ca8d8e..0ea0ccaceab 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -6,8 +6,9 @@ use crate::astconv::{
 use crate::errors::AssocTypeBindingNotAllowed;
 use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{struct_span_err, Applicability, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::ty::{
@@ -43,23 +44,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
+        let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut DiagnosticBuilder<'_>| {
+            let suggestions = vec![
+                (arg.span().shrink_to_lo(), String::from("{ ")),
+                (arg.span().shrink_to_hi(), String::from(" }")),
+            ];
+            err.multipart_suggestion(
+                "if this generic argument was intended as a const parameter, \
+                 surround it with braces",
+                suggestions,
+                Applicability::MaybeIncorrect,
+            );
+        };
+
         // Specific suggestion set for diagnostics
         match (arg, &param.kind) {
             (
-                GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
-                GenericParamDefKind::Const { .. },
-            ) => {
-                let suggestions = vec![
-                    (arg.span().shrink_to_lo(), String::from("{ ")),
-                    (arg.span().shrink_to_hi(), String::from(" }")),
-                ];
-                err.multipart_suggestion(
-                    "if this generic argument was intended as a const parameter, \
-                try surrounding it with braces:",
-                    suggestions,
-                    Applicability::MaybeIncorrect,
-                );
-            }
+                GenericArg::Type(hir::Ty {
+                    kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
+                    ..
+                }),
+                GenericParamDefKind::Const,
+            ) => match path.res {
+                Res::Err => {
+                    add_braces_suggestion(arg, &mut err);
+                    err.set_primary_message(
+                        "unresolved item provided when a constant was expected",
+                    )
+                    .emit();
+                    return;
+                }
+                Res::Def(DefKind::TyParam, src_def_id) => {
+                    if let Some(param_local_id) = param.def_id.as_local() {
+                        let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
+                        let param_name = tcx.hir().ty_param_name(param_hir_id);
+                        let param_type = tcx.type_of(param.def_id);
+                        if param_type.is_suggestable() {
+                            err.span_suggestion(
+                                tcx.def_span(src_def_id),
+                                "consider changing this type paramater to a `const`-generic",
+                                format!("const {}: {}", param_name, param_type),
+                                Applicability::MaybeIncorrect,
+                            );
+                        };
+                    }
+                }
+                _ => add_braces_suggestion(arg, &mut err),
+            },
+            (
+                GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
+                GenericParamDefKind::Const,
+            ) => add_braces_suggestion(arg, &mut err),
             (
                 GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
                 GenericParamDefKind::Const { .. },
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index c9cc47b83e3..2e1fb44d3b5 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2210,8 +2210,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 self.res_to_ty(opt_self_ty, path, false)
             }
             hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
-                let opaque_ty = tcx.hir().expect_item(item_id.id);
-                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+                let opaque_ty = tcx.hir().item(item_id);
+                let def_id = item_id.def_id.to_def_id();
 
                 match opaque_ty.kind {
                     hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
@@ -2374,7 +2374,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             crate::collect::placeholder_type_error(
                 tcx,
                 ident_span.map(|sp| sp.shrink_to_hi()),
-                &generics.params[..],
+                generics.params,
                 visitor.0,
                 true,
                 hir_ty,
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 012ccb1af46..5d7f5bf1c7b 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -7,8 +7,9 @@ use rustc_attr as attr;
 use rustc_errors::{Applicability, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{ItemKind, Node};
+use rustc_hir::{def::Res, ItemKind, Node, PathSegment};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -373,8 +374,7 @@ pub(super) fn check_fn<'a, 'tcx>(
     (fcx, gen_ty)
 }
 
-pub(super) fn check_struct(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
-    let def_id = tcx.hir().local_def_id(id);
+fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
     check_representable(tcx, span, def_id);
@@ -387,8 +387,7 @@ pub(super) fn check_struct(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
     check_packed(tcx, span, def);
 }
 
-fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
-    let def_id = tcx.hir().local_def_id(id);
+fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) {
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
     check_representable(tcx, span, def_id);
@@ -515,10 +514,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         }
     }
 
-    #[derive(Debug)]
     struct ProhibitOpaqueVisitor<'tcx> {
         opaque_identity_ty: Ty<'tcx>,
         generics: &'tcx ty::Generics,
+        tcx: TyCtxt<'tcx>,
+        selftys: Vec<(Span, Option<String>)>,
     }
 
     impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
@@ -535,6 +535,29 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         }
     }
 
+    impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
+        type Map = rustc_middle::hir::map::Map<'tcx>;
+
+        fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+            hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
+        }
+
+        fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
+            match arg.kind {
+                hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
+                    [PathSegment { res: Some(Res::SelfTy(_, impl_ref)), .. }] => {
+                        let impl_ty_name =
+                            impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id));
+                        self.selftys.push((path.span, impl_ty_name));
+                    }
+                    _ => {}
+                },
+                _ => {}
+            }
+            hir::intravisit::walk_ty(self, arg);
+        }
+    }
+
     if let ItemKind::OpaqueTy(hir::OpaqueTy {
         origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn,
         ..
@@ -546,17 +569,20 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
                 InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
             ),
             generics: tcx.generics_of(def_id),
+            tcx,
+            selftys: vec![],
         };
         let prohibit_opaque = tcx
             .explicit_item_bounds(def_id)
             .iter()
             .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
         debug!(
-            "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
-            prohibit_opaque, visitor
+            "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}",
+            prohibit_opaque, visitor.opaque_identity_ty, visitor.generics
         );
 
         if let Some(ty) = prohibit_opaque.break_value() {
+            visitor.visit_item(&item);
             let is_async = match item.kind {
                 ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
                     matches!(origin, hir::OpaqueTyOrigin::AsyncFn)
@@ -573,15 +599,13 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
                 if is_async { "async fn" } else { "impl Trait" },
             );
 
-            if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
-                if snippet == "Self" {
-                    err.span_suggestion(
-                        span,
-                        "consider spelling out the type instead",
-                        format!("{:?}", ty),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+            for (span, name) in visitor.selftys {
+                err.span_suggestion(
+                    span,
+                    "consider spelling out the type instead",
+                    name.unwrap_or_else(|| format!("{:?}", ty)),
+                    Applicability::MaybeIncorrect,
+                );
             }
             err.emit();
         }
@@ -683,34 +707,32 @@ fn check_opaque_meets_bounds<'tcx>(
 
 pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
     debug!(
-        "check_item_type(it.hir_id={}, it.name={})",
-        it.hir_id,
-        tcx.def_path_str(tcx.hir().local_def_id(it.hir_id).to_def_id())
+        "check_item_type(it.def_id={:?}, it.name={})",
+        it.def_id,
+        tcx.def_path_str(it.def_id.to_def_id())
     );
     let _indenter = indenter();
     match it.kind {
         // Consts can play a role in type-checking, so they are included here.
         hir::ItemKind::Static(..) => {
-            let def_id = tcx.hir().local_def_id(it.hir_id);
-            tcx.ensure().typeck(def_id);
-            maybe_check_static_with_link_section(tcx, def_id, it.span);
-            check_static_inhabited(tcx, def_id, it.span);
+            tcx.ensure().typeck(it.def_id);
+            maybe_check_static_with_link_section(tcx, it.def_id, it.span);
+            check_static_inhabited(tcx, it.def_id, it.span);
         }
         hir::ItemKind::Const(..) => {
-            tcx.ensure().typeck(tcx.hir().local_def_id(it.hir_id));
+            tcx.ensure().typeck(it.def_id);
         }
         hir::ItemKind::Enum(ref enum_definition, _) => {
-            check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
+            check_enum(tcx, it.span, &enum_definition.variants, it.def_id);
         }
         hir::ItemKind::Fn(..) => {} // entirely within check_item_body
         hir::ItemKind::Impl(ref impl_) => {
-            debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
-            let impl_def_id = tcx.hir().local_def_id(it.hir_id);
-            if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
+            debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id);
+            if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) {
                 check_impl_items_against_trait(
                     tcx,
                     it.span,
-                    impl_def_id,
+                    it.def_id,
                     impl_trait_ref,
                     &impl_.items,
                 );
@@ -719,8 +741,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             }
         }
         hir::ItemKind::Trait(_, _, _, _, ref items) => {
-            let def_id = tcx.hir().local_def_id(it.hir_id);
-            check_on_unimplemented(tcx, def_id.to_def_id(), it);
+            check_on_unimplemented(tcx, it.def_id.to_def_id(), it);
 
             for item in items.iter() {
                 let item = tcx.hir().trait_item(item.id);
@@ -730,16 +751,15 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                         fn_maybe_err(tcx, item.ident.span, abi);
                     }
                     hir::TraitItemKind::Type(.., Some(_default)) => {
-                        let item_def_id = tcx.hir().local_def_id(item.hir_id).to_def_id();
-                        let assoc_item = tcx.associated_item(item_def_id);
+                        let assoc_item = tcx.associated_item(item.def_id);
                         let trait_substs =
-                            InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                            InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
                         let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds(
                             tcx,
                             assoc_item,
                             assoc_item,
                             item.span,
-                            ty::TraitRef { def_id: def_id.to_def_id(), substs: trait_substs },
+                            ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs },
                         );
                     }
                     _ => {}
@@ -747,10 +767,10 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             }
         }
         hir::ItemKind::Struct(..) => {
-            check_struct(tcx, it.hir_id, it.span);
+            check_struct(tcx, it.def_id, it.span);
         }
         hir::ItemKind::Union(..) => {
-            check_union(tcx, it.hir_id, it.span);
+            check_union(tcx, it.def_id, it.span);
         }
         hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
             // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
@@ -758,16 +778,13 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
             // See https://github.com/rust-lang/rust/issues/75100
             if !tcx.sess.opts.actually_rustdoc {
-                let def_id = tcx.hir().local_def_id(it.hir_id);
-
-                let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
-                check_opaque(tcx, def_id, substs, it.span, &origin);
+                let substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
+                check_opaque(tcx, it.def_id, substs, it.span, &origin);
             }
         }
         hir::ItemKind::TyAlias(..) => {
-            let def_id = tcx.hir().local_def_id(it.hir_id);
-            let pty_ty = tcx.type_of(def_id);
-            let generics = tcx.generics_of(def_id);
+            let pty_ty = tcx.type_of(it.def_id);
+            let generics = tcx.generics_of(it.def_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
         hir::ItemKind::ForeignMod { abi, items } => {
@@ -785,7 +802,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                 }
             } else {
                 for item in items {
-                    let def_id = tcx.hir().local_def_id(item.id.hir_id);
+                    let def_id = item.id.def_id;
                     let generics = tcx.generics_of(def_id);
                     let own_counts = generics.own_counts();
                     if generics.params.len() - own_counts.lifetimes != 0 {
@@ -835,9 +852,8 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
 }
 
 pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
-    let item_def_id = tcx.hir().local_def_id(item.hir_id);
     // an error would be reported if this fails.
-    let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id.to_def_id());
+    let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item.def_id.to_def_id());
 }
 
 pub(super) fn check_specialization_validity<'tcx>(
@@ -938,7 +954,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
     for impl_item in impl_items {
-        let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
+        let ty_impl_item = tcx.associated_item(impl_item.def_id);
 
         let mut items =
             associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id);
@@ -1345,13 +1361,12 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty
 }
 
 #[allow(trivial_numeric_casts)]
-pub fn check_enum<'tcx>(
+fn check_enum<'tcx>(
     tcx: TyCtxt<'tcx>,
     sp: Span,
     vs: &'tcx [hir::Variant<'tcx>],
-    id: hir::HirId,
+    def_id: LocalDefId,
 ) {
-    let def_id = tcx.hir().local_def_id(id);
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
 
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index d37d6bc4f2d..a30a8107933 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -823,11 +823,11 @@ fn compare_synthetic_generics<'tcx>(
                         // FIXME: this is obviously suboptimal since the name can already be used
                         // as another generic argument
                         let new_name = tcx.sess.source_map().span_to_snippet(trait_span).ok()?;
-                        let trait_m = tcx.hir().local_def_id_to_hir_id(trait_m.def_id.as_local()?);
-                        let trait_m = tcx.hir().trait_item(hir::TraitItemId { hir_id: trait_m });
+                        let trait_m = trait_m.def_id.as_local()?;
+                        let trait_m = tcx.hir().trait_item(hir::TraitItemId { def_id: trait_m });
 
-                        let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
-                        let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
+                        let impl_m = impl_m.def_id.as_local()?;
+                        let impl_m = tcx.hir().impl_item(hir::ImplItemId { def_id: impl_m });
 
                         // in case there are no generics, take the spot between the function name
                         // and the opening paren of the argument list
@@ -860,8 +860,8 @@ fn compare_synthetic_generics<'tcx>(
                 (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
                     err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
                     (|| {
-                        let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
-                        let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
+                        let impl_m = impl_m.def_id.as_local()?;
+                        let impl_m = tcx.hir().impl_item(hir::ImplItemId { def_id: impl_m });
                         let input_tys = match impl_m.kind {
                             hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
                             _ => unreachable!(),
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index bc1a07801ae..9e6c11d9ddd 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -897,7 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return (
                     path.res,
                     opt_qself.as_ref().map(|qself| self.to_ty(qself)),
-                    &path.segments[..],
+                    path.segments,
                 );
             }
             QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index e99db7a247c..dedf96863ea 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -9,7 +9,6 @@ use crate::require_same_types;
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, TyCtxt};
@@ -21,7 +20,6 @@ use std::iter;
 fn equate_intrinsic_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     it: &hir::ForeignItem<'_>,
-    def_id: DefId,
     n_tps: usize,
     sig: ty::PolyFnSig<'tcx>,
 ) {
@@ -35,7 +33,7 @@ fn equate_intrinsic_type<'tcx>(
         }
     }
 
-    let i_n_tps = tcx.generics_of(def_id).own_counts().types;
+    let i_n_tps = tcx.generics_of(it.def_id).own_counts().types;
     if i_n_tps != n_tps {
         let span = match it.kind {
             hir::ForeignItemKind::Fn(_, _, ref generics) => generics.span,
@@ -51,8 +49,8 @@ fn equate_intrinsic_type<'tcx>(
     }
 
     let fty = tcx.mk_fn_ptr(sig);
-    let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType);
-    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
+    let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
+    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
 }
 
 /// Returns `true` if the given intrinsic is unsafe to call or not.
@@ -100,8 +98,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
 /// and in `library/core/src/intrinsics.rs`.
 pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
-    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
-    let intrinsic_name = tcx.item_name(def_id);
+    let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
     let name_str = intrinsic_name.as_str();
 
     let mk_va_list_ty = |mutbl| {
@@ -370,7 +367,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     };
     let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
     let sig = ty::Binder::bind(sig);
-    equate_intrinsic_type(tcx, it, def_id, n_tps, sig)
+    equate_intrinsic_type(tcx, it, n_tps, sig)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -380,7 +377,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         tcx.mk_ty_param(n, name)
     };
 
-    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
     let name = it.ident.name;
 
     let (n_tps, inputs, output) = match name {
@@ -464,5 +460,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         Abi::PlatformIntrinsic,
     );
     let sig = ty::Binder::dummy(sig);
-    equate_intrinsic_type(tcx, it, def_id, n_tps, sig)
+    equate_intrinsic_type(tcx, it, n_tps, sig)
 }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index d49c7cae822..faa47230d3a 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -11,7 +11,6 @@ use rustc_hir::intravisit;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::fast_reject::simplify_type;
 use rustc_middle::ty::print::with_crate_prefix;
 use rustc_middle::ty::{
@@ -600,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     });
                                     if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
                                         if let Some(g) = kind.generics() {
-                                            let key = match &g.where_clause.predicates[..] {
+                                            let key = match g.where_clause.predicates {
                                                 [.., pred] => (pred.span().shrink_to_hi(), false),
                                                 [] => (
                                                     g.where_clause
@@ -1352,17 +1351,15 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
 
     // Crate-local:
 
-    struct Visitor<'a, 'tcx> {
-        map: &'a hir_map::Map<'tcx>,
+    struct Visitor<'a> {
         traits: &'a mut Vec<DefId>,
     }
 
-    impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
+    impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
         fn visit_item(&mut self, i: &'v hir::Item<'v>) {
             match i.kind {
                 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
-                    let def_id = self.map.local_def_id(i.hir_id);
-                    self.traits.push(def_id.to_def_id());
+                    self.traits.push(i.def_id.to_def_id());
                 }
                 _ => (),
             }
@@ -1375,7 +1372,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
         fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
     }
 
-    tcx.hir().krate().visit_all_item_likes(&mut Visitor { map: &tcx.hir(), traits: &mut traits });
+    tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
 
     // Cross-crate:
 
@@ -1445,8 +1442,8 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
             return;
         }
         // Find a `use` statement.
-        for item_id in module.item_ids {
-            let item = self.tcx.hir().expect_item(item_id.id);
+        for &item_id in module.item_ids {
+            let item = self.tcx.hir().item(item_id);
             match item.kind {
                 hir::ItemKind::Use(..) => {
                     // Don't suggest placing a `use` before the prelude
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index d097f863ad2..69c09528662 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -180,7 +180,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     debug!("seed place {:?}", place);
 
                     let upvar_id = ty::UpvarId::new(*var_hir_id, local_def_id);
-                    let capture_kind = self.init_capture_kind(capture_clause, upvar_id, span);
+                    let capture_kind =
+                        self.init_capture_kind_for_place(&place, capture_clause, upvar_id, span);
                     let fake_info = ty::CaptureInfo {
                         capture_kind_expr_id: None,
                         path_expr_id: None,
@@ -205,11 +206,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If we have an origin, store it.
             if let Some(origin) = delegate.current_origin.clone() {
                 let origin = if self.tcx.features().capture_disjoint_fields {
-                    origin
+                    (origin.0, restrict_capture_precision(origin.1))
                 } else {
-                    // FIXME(project-rfc-2229#31): Once the changes to support reborrowing are
-                    //                             made, make sure we are selecting and restricting
-                    //                             the origin correctly.
                     (origin.0, Place { projections: vec![], ..origin.1 })
                 };
 
@@ -449,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 base => bug!("Expected upvar, found={:?}", base),
             };
 
-            let place = restrict_capture_precision(place, capture_info.capture_kind);
+            let place = restrict_capture_precision(place);
 
             let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
                 None => {
@@ -897,15 +895,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn init_capture_kind(
+    fn init_capture_kind_for_place(
         &self,
+        place: &Place<'tcx>,
         capture_clause: hir::CaptureBy,
         upvar_id: ty::UpvarId,
         closure_span: Span,
     ) -> ty::UpvarCapture<'tcx> {
         match capture_clause {
-            hir::CaptureBy::Value => ty::UpvarCapture::ByValue(None),
-            hir::CaptureBy::Ref => {
+            // In case of a move closure if the data is accessed through a reference we
+            // want to capture by ref to allow precise capture using reborrows.
+            //
+            // If the data will be moved out of this place, then the place will be truncated
+            // at the first Deref in `adjust_upvar_borrow_kind_for_consume` and then moved into
+            // the closure.
+            hir::CaptureBy::Value if !place.deref_tys().any(ty::TyS::is_ref) => {
+                ty::UpvarCapture::ByValue(None)
+            }
+            hir::CaptureBy::Value | hir::CaptureBy::Ref => {
                 let origin = UpvarRegion(upvar_id, closure_span);
                 let upvar_region = self.next_region_var(origin);
                 let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
@@ -1109,12 +1116,25 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
             place_with_id, diag_expr_id, mode
         );
 
-        // we only care about moves
-        match mode {
-            euv::Copy => {
+        match (self.capture_clause, mode) {
+            // In non-move closures, we only care about moves
+            (hir::CaptureBy::Ref, euv::Copy) => return,
+
+            // We want to capture Copy types that read through a ref via a reborrow
+            (hir::CaptureBy::Value, euv::Copy)
+                if place_with_id.place.deref_tys().any(ty::TyS::is_ref) =>
+            {
                 return;
             }
-            euv::Move => {}
+
+            (hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {}
+        };
+
+        let place = truncate_capture_for_move(place_with_id.place.clone());
+        let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
+
+        if !self.capture_information.contains_key(&place) {
+            self.init_capture_info_for_place(&place_with_id, diag_expr_id);
         }
 
         let tcx = self.fcx.tcx;
@@ -1128,13 +1148,15 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
 
         let usage_span = tcx.hir().span(diag_expr_id);
 
-        // To move out of an upvar, this must be a FnOnce closure
-        self.adjust_closure_kind(
-            upvar_id.closure_expr_id,
-            ty::ClosureKind::FnOnce,
-            usage_span,
-            place_with_id.place.clone(),
-        );
+        if matches!(mode, euv::Move) {
+            // To move out of an upvar, this must be a FnOnce closure
+            self.adjust_closure_kind(
+                upvar_id.closure_expr_id,
+                ty::ClosureKind::FnOnce,
+                usage_span,
+                place.clone(),
+            );
+        }
 
         let capture_info = ty::CaptureInfo {
             capture_kind_expr_id: Some(diag_expr_id),
@@ -1317,8 +1339,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
         if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
             assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id);
 
-            let capture_kind =
-                self.fcx.init_capture_kind(self.capture_clause, upvar_id, self.closure_span);
+            let capture_kind = self.fcx.init_capture_kind_for_place(
+                &place_with_id.place,
+                self.capture_clause,
+                upvar_id,
+                self.closure_span,
+            );
 
             let expr_id = Some(diag_expr_id);
             let capture_info = ty::CaptureInfo {
@@ -1392,15 +1418,10 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
 }
 
 /// Truncate projections so that following rules are obeyed by the captured `place`:
-///
-/// - No Derefs in move closure, this will result in value behind a reference getting moved.
 /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
 ///   them completely.
 /// - No Index projections are captured, since arrays are captured completely.
-fn restrict_capture_precision<'tcx>(
-    mut place: Place<'tcx>,
-    capture_kind: ty::UpvarCapture<'tcx>,
-) -> Place<'tcx> {
+fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
     if place.projections.is_empty() {
         // Nothing to do here
         return place;
@@ -1412,7 +1433,6 @@ fn restrict_capture_precision<'tcx>(
     }
 
     let mut truncated_length = usize::MAX;
-    let mut first_deref_projection = usize::MAX;
 
     for (i, proj) in place.projections.iter().enumerate() {
         if proj.ty.is_unsafe_ptr() {
@@ -1426,31 +1446,30 @@ fn restrict_capture_precision<'tcx>(
                 truncated_length = truncated_length.min(i);
                 break;
             }
-            ProjectionKind::Deref => {
-                // We only drop Derefs in case of move closures
-                // There might be an index projection or raw ptr ahead, so we don't stop here.
-                first_deref_projection = first_deref_projection.min(i);
-            }
+            ProjectionKind::Deref => {}
             ProjectionKind::Field(..) => {} // ignore
             ProjectionKind::Subslice => {}  // We never capture this
         }
     }
 
-    let length = place
-        .projections
-        .len()
-        .min(truncated_length)
-        // In case of capture `ByValue` we want to not capture derefs
-        .min(match capture_kind {
-            ty::UpvarCapture::ByValue(..) => first_deref_projection,
-            ty::UpvarCapture::ByRef(..) => usize::MAX,
-        });
+    let length = place.projections.len().min(truncated_length);
 
     place.projections.truncate(length);
 
     place
 }
 
+/// Truncates a place so that the resultant capture doesn't move data out of a reference
+fn truncate_capture_for_move(mut place: Place<'tcx>) -> Place<'tcx> {
+    if let Some(i) = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref) {
+        // We only drop Derefs in case of move closures
+        // There might be an index projection or raw ptr ahead, so we don't stop here.
+        place.projections.truncate(i);
+    }
+
+    place
+}
+
 fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
     let variable_name = match place.base {
         PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(),
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index c90db4786e3..00c6550835b 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -80,8 +80,8 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let item = tcx.hir().expect_item(hir_id);
 
     debug!(
-        "check_item_well_formed(it.hir_id={:?}, it.name={})",
-        item.hir_id,
+        "check_item_well_formed(it.def_id={:?}, it.name={})",
+        item.def_id,
         tcx.def_path_str(def_id.to_def_id())
     );
 
@@ -105,7 +105,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         // for `T`
         hir::ItemKind::Impl(ref impl_) => {
             let is_auto = tcx
-                .impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
+                .impl_trait_ref(item.def_id)
                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
             if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
                 let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
@@ -141,23 +141,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             }
         }
         hir::ItemKind::Fn(ref sig, ..) => {
-            check_item_fn(tcx, item.hir_id, item.ident, item.span, sig.decl);
+            check_item_fn(tcx, item.hir_id(), item.ident, item.span, sig.decl);
         }
         hir::ItemKind::Static(ref ty, ..) => {
-            check_item_type(tcx, item.hir_id, ty.span, false);
+            check_item_type(tcx, item.hir_id(), ty.span, false);
         }
         hir::ItemKind::Const(ref ty, ..) => {
-            check_item_type(tcx, item.hir_id, ty.span, false);
+            check_item_type(tcx, item.hir_id(), ty.span, false);
         }
         hir::ItemKind::ForeignMod { items, .. } => {
             for it in items.iter() {
                 let it = tcx.hir().foreign_item(it.id);
                 match it.kind {
                     hir::ForeignItemKind::Fn(ref decl, ..) => {
-                        check_item_fn(tcx, it.hir_id, it.ident, it.span, decl)
+                        check_item_fn(tcx, it.hir_id(), it.ident, it.span, decl)
                     }
                     hir::ForeignItemKind::Static(ref ty, ..) => {
-                        check_item_type(tcx, it.hir_id, ty.span, true)
+                        check_item_type(tcx, it.hir_id(), ty.span, true)
                     }
                     hir::ForeignItemKind::Type => (),
                 }
@@ -197,7 +197,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => None,
     };
     check_object_unsafe_self_trait_by_name(tcx, &trait_item);
-    check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
+    check_associated_item(tcx, trait_item.hir_id(), trait_item.span, method_sig);
 }
 
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
@@ -213,9 +213,9 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
 /// Detect when an object unsafe trait is referring to itself in one of its associated items.
 /// When this is done, suggest using `Self` instead.
 fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
-    let (trait_name, trait_def_id) = match tcx.hir().get(tcx.hir().get_parent_item(item.hir_id)) {
+    let (trait_name, trait_def_id) = match tcx.hir().get(tcx.hir().get_parent_item(item.hir_id())) {
         hir::Node::Item(item) => match item.kind {
-            hir::ItemKind::Trait(..) => (item.ident, tcx.hir().local_def_id(item.hir_id)),
+            hir::ItemKind::Trait(..) => (item.ident, item.def_id),
             _ => return,
         },
         _ => return,
@@ -271,7 +271,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => None,
     };
 
-    check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
+    check_associated_item(tcx, impl_item.hir_id(), impl_item.span, method_sig);
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -432,7 +432,7 @@ fn check_associated_item(
 }
 
 fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> {
-    for_id(tcx, item.hir_id, item.span)
+    for_id(tcx, item.hir_id(), item.span)
 }
 
 fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> {
@@ -465,8 +465,7 @@ fn check_type_defn<'tcx, F>(
 {
     for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
         let variants = lookup_fields(fcx);
-        let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
-        let packed = fcx.tcx.adt_def(def_id).repr.packed();
+        let packed = fcx.tcx.adt_def(item.def_id).repr.packed();
 
         for variant in &variants {
             // For DST, or when drop needs to copy things around, all
@@ -482,7 +481,7 @@ fn check_type_defn<'tcx, F>(
                         // Just treat unresolved type expression as if it needs drop.
                         true
                     } else {
-                        ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
+                        ty.needs_drop(fcx_tcx, fcx_tcx.param_env(item.def_id))
                     }
                 }
             };
@@ -541,7 +540,7 @@ fn check_type_defn<'tcx, F>(
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, def_id.to_def_id(), None);
+        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
 
         // No implied bounds in a struct definition.
         vec![]
@@ -549,15 +548,13 @@ fn check_type_defn<'tcx, F>(
 }
 
 fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
-    debug!("check_trait: {:?}", item.hir_id);
+    debug!("check_trait: {:?}", item.def_id);
 
-    let trait_def_id = tcx.hir().local_def_id(item.hir_id);
-
-    let trait_def = tcx.trait_def(trait_def_id);
+    let trait_def = tcx.trait_def(item.def_id);
     if trait_def.is_marker
         || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
     {
-        for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) {
+        for associated_def_id in &*tcx.associated_item_def_ids(item.def_id) {
             struct_span_err!(
                 tcx.sess,
                 tcx.def_span(*associated_def_id),
@@ -569,7 +566,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     }
 
     for_item(tcx, item).with_fcx(|fcx, _| {
-        check_where_clauses(tcx, fcx, item.span, trait_def_id.to_def_id(), None);
+        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
 
         vec![]
     });
@@ -665,14 +662,12 @@ fn check_impl<'tcx>(
     debug!("check_impl: {:?}", item);
 
     for_item(tcx, item).with_fcx(|fcx, tcx| {
-        let item_def_id = fcx.tcx.hir().local_def_id(item.hir_id);
-
         match *ast_trait_ref {
             Some(ref ast_trait_ref) => {
                 // `#[rustc_reservation_impl]` impls are not real impls and
                 // therefore don't need to be WF (the trait's `Self: Trait` predicate
                 // won't hold).
-                let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
+                let trait_ref = fcx.tcx.impl_trait_ref(item.def_id).unwrap();
                 let trait_ref =
                     fcx.normalize_associated_types_in(ast_trait_ref.path.span, trait_ref);
                 let obligations = traits::wf::trait_obligations(
@@ -688,7 +683,7 @@ fn check_impl<'tcx>(
                 }
             }
             None => {
-                let self_ty = fcx.tcx.type_of(item_def_id);
+                let self_ty = fcx.tcx.type_of(item.def_id);
                 let self_ty = fcx.normalize_associated_types_in(item.span, self_ty);
                 fcx.register_wf_obligation(
                     self_ty.into(),
@@ -698,9 +693,9 @@ fn check_impl<'tcx>(
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, item_def_id.to_def_id(), None);
+        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
 
-        fcx.impl_implied_bounds(item_def_id.to_def_id(), item.span)
+        fcx.impl_implied_bounds(item.def_id.to_def_id(), item.span)
     });
 }
 
@@ -1238,15 +1233,14 @@ fn check_variances_for_type_defn<'tcx>(
     item: &hir::Item<'tcx>,
     hir_generics: &hir::Generics<'_>,
 ) {
-    let item_def_id = tcx.hir().local_def_id(item.hir_id);
-    let ty = tcx.type_of(item_def_id);
+    let ty = tcx.type_of(item.def_id);
     if tcx.has_error_field(ty) {
         return;
     }
 
-    let ty_predicates = tcx.predicates_of(item_def_id);
+    let ty_predicates = tcx.predicates_of(item.def_id);
     assert_eq!(ty_predicates.parent, None);
-    let variances = tcx.variances_of(item_def_id);
+    let variances = tcx.variances_of(item.def_id);
 
     let mut constrained_parameters: FxHashSet<_> = variances
         .iter()
@@ -1354,22 +1348,19 @@ impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
 
     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
         debug!("visit_item: {:?}", i);
-        let def_id = self.tcx.hir().local_def_id(i.hir_id);
-        self.tcx.ensure().check_item_well_formed(def_id);
+        self.tcx.ensure().check_item_well_formed(i.def_id);
         hir_visit::walk_item(self, i);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         debug!("visit_trait_item: {:?}", trait_item);
-        let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
-        self.tcx.ensure().check_trait_item_well_formed(def_id);
+        self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
         hir_visit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         debug!("visit_impl_item: {:?}", impl_item);
-        let def_id = self.tcx.hir().local_def_id(impl_item.hir_id);
-        self.tcx.ensure().check_impl_item_well_formed(def_id);
+        self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
         hir_visit::walk_impl_item(self, impl_item);
     }
 
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index 31121ece898..e1743a5dfc1 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -28,7 +28,7 @@ impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> {
             return;
         }
         if let hir::ItemKind::Use(ref path, _) = item.kind {
-            self.check_import(item.hir_id, path.span);
+            self.check_import(item.item_id(), path.span);
         }
     }
 
@@ -45,24 +45,28 @@ struct CheckVisitor<'tcx> {
 }
 
 impl CheckVisitor<'tcx> {
-    fn check_import(&self, id: hir::HirId, span: Span) {
-        let def_id = self.tcx.hir().local_def_id(id);
-        if !self.tcx.maybe_unused_trait_import(def_id) {
+    fn check_import(&self, item_id: hir::ItemId, span: Span) {
+        if !self.tcx.maybe_unused_trait_import(item_id.def_id) {
             return;
         }
 
-        if self.used_trait_imports.contains(&def_id) {
+        if self.used_trait_imports.contains(&item_id.def_id) {
             return;
         }
 
-        self.tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, id, span, |lint| {
-            let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                format!("unused import: `{}`", snippet)
-            } else {
-                "unused import".to_owned()
-            };
-            lint.build(&msg).emit();
-        });
+        self.tcx.struct_span_lint_hir(
+            lint::builtin::UNUSED_IMPORTS,
+            item_id.hir_id(),
+            span,
+            |lint| {
+                let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    format!("unused import: `{}`", snippet)
+                } else {
+                    "unused import".to_owned()
+                };
+                lint.build(&msg).emit();
+            },
+        );
     }
 }
 
@@ -109,7 +113,6 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
     // Collect all the extern crates (in a reliable order).
     let mut crates_to_lint = vec![];
     tcx.hir().krate().visit_all_item_likes(&mut CollectExternCrateVisitor {
-        tcx,
         crates_to_lint: &mut crates_to_lint,
     });
 
@@ -189,8 +192,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
     }
 }
 
-struct CollectExternCrateVisitor<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
+struct CollectExternCrateVisitor<'a> {
     crates_to_lint: &'a mut Vec<ExternCrateToLint>,
 }
 
@@ -211,12 +213,11 @@ struct ExternCrateToLint {
     warn_if_unused: bool,
 }
 
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
+impl<'a, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
-            let extern_crate_def_id = self.tcx.hir().local_def_id(item.hir_id);
             self.crates_to_lint.push(ExternCrateToLint {
-                def_id: extern_crate_def_id.to_def_id(),
+                def_id: item.def_id.to_def_id(),
                 span: item.span,
                 orig_name,
                 warn_if_unused: !item.ident.as_str().starts_with('_'),
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 6726b9b4a4b..5b44cb7eae5 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -38,8 +38,7 @@ impl<'tcx> Checker<'tcx> {
         F: FnMut(TyCtxt<'tcx>, LocalDefId),
     {
         if Some(self.trait_def_id) == trait_def_id {
-            for &impl_id in self.tcx.hir().trait_impls(self.trait_def_id) {
-                let impl_def_id = self.tcx.hir().local_def_id(impl_id);
+            for &impl_def_id in self.tcx.hir().trait_impls(self.trait_def_id) {
                 f(self.tcx, impl_def_id);
             }
         }
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index 8a500852a03..cc592c7a260 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -50,8 +50,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             _ => return,
         };
 
-        let def_id = self.tcx.hir().local_def_id(item.hir_id);
-        let self_ty = self.tcx.type_of(def_id);
+        let self_ty = self.tcx.type_of(item.def_id);
         let lang_items = self.tcx.lang_items();
         match *self_ty.kind() {
             ty::Adt(def, _) => {
@@ -65,7 +64,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Bool => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.bool_impl(),
                     None,
                     "bool",
@@ -76,7 +75,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Char => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.char_impl(),
                     None,
                     "char",
@@ -87,7 +86,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Str => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.str_impl(),
                     lang_items.str_alloc_impl(),
                     "str",
@@ -98,7 +97,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.slice_u8_impl(),
                     lang_items.slice_u8_alloc_impl(),
                     "slice_u8",
@@ -109,7 +108,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Slice(_) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.slice_impl(),
                     lang_items.slice_alloc_impl(),
                     "slice",
@@ -120,7 +119,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Array(_, _) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.array_impl(),
                     None,
                     "array",
@@ -133,7 +132,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
                 if matches!(inner.kind(), ty::Slice(_)) =>
             {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.const_slice_ptr_impl(),
                     None,
                     "const_slice_ptr",
@@ -146,7 +145,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
                 if matches!(inner.kind(), ty::Slice(_)) =>
             {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.mut_slice_ptr_impl(),
                     None,
                     "mut_slice_ptr",
@@ -157,7 +156,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.const_ptr_impl(),
                     None,
                     "const_ptr",
@@ -168,7 +167,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.mut_ptr_impl(),
                     None,
                     "mut_ptr",
@@ -179,7 +178,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::I8) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.i8_impl(),
                     None,
                     "i8",
@@ -190,7 +189,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::I16) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.i16_impl(),
                     None,
                     "i16",
@@ -201,7 +200,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::I32) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.i32_impl(),
                     None,
                     "i32",
@@ -212,7 +211,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::I64) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.i64_impl(),
                     None,
                     "i64",
@@ -223,7 +222,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::I128) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.i128_impl(),
                     None,
                     "i128",
@@ -234,7 +233,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Int(ty::IntTy::Isize) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.isize_impl(),
                     None,
                     "isize",
@@ -245,7 +244,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::U8) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.u8_impl(),
                     None,
                     "u8",
@@ -256,7 +255,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::U16) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.u16_impl(),
                     None,
                     "u16",
@@ -267,7 +266,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::U32) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.u32_impl(),
                     None,
                     "u32",
@@ -278,7 +277,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::U64) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.u64_impl(),
                     None,
                     "u64",
@@ -289,7 +288,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::U128) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.u128_impl(),
                     None,
                     "u128",
@@ -300,7 +299,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Uint(ty::UintTy::Usize) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.usize_impl(),
                     None,
                     "usize",
@@ -311,7 +310,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Float(ty::FloatTy::F32) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.f32_impl(),
                     lang_items.f32_runtime_impl(),
                     "f32",
@@ -322,7 +321,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Float(ty::FloatTy::F64) => {
                 self.check_primitive_impl(
-                    def_id,
+                    item.def_id,
                     lang_items.f64_impl(),
                     lang_items.f64_runtime_impl(),
                     "f64",
@@ -369,9 +368,8 @@ impl InherentCollect<'tcx> {
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
-            let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
             let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
-            vec.push(impl_def_id.to_def_id());
+            vec.push(item.def_id.to_def_id());
         } else {
             struct_span_err!(
                 self.tcx.sess,
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
index 50d88674328..29654099992 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
@@ -123,8 +123,7 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Trait(..)
             | hir::ItemKind::Union(..) => {
-                let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
-                let impls = self.tcx.inherent_impls(ty_def_id);
+                let impls = self.tcx.inherent_impls(item.def_id);
 
                 // If there is only one inherent impl block,
                 // there is nothing to overlap check it with
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs
index 4294450333c..05906817914 100644
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ b/compiler/rustc_typeck/src/coherence/mod.rs
@@ -172,8 +172,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
     tcx.ensure().specialization_graph_of(def_id);
 
     let impls = tcx.hir().trait_impls(def_id);
-    for &hir_id in impls {
-        let impl_def_id = tcx.hir().local_def_id(hir_id);
+    for &impl_def_id in impls {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
 
         check_impl(tcx, impl_def_id, trait_ref);
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index 9333aac6018..05932427bcf 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -24,7 +24,6 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let def_id = self.tcx.hir().local_def_id(item.hir_id);
         // "Trait" impl
         if let hir::ItemKind::Impl(hir::Impl {
             generics, of_trait: Some(ref tr), self_ty, ..
@@ -32,13 +31,13 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
         {
             debug!(
                 "coherence2::orphan check: trait impl {}",
-                self.tcx.hir().node_to_string(item.hir_id)
+                self.tcx.hir().node_to_string(item.hir_id())
             );
-            let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
+            let trait_ref = self.tcx.impl_trait_ref(item.def_id).unwrap();
             let trait_def_id = trait_ref.def_id;
             let sm = self.tcx.sess.source_map();
             let sp = sm.guess_head_span(item.span);
-            match traits::orphan_check(self.tcx, def_id.to_def_id()) {
+            match traits::orphan_check(self.tcx, item.def_id.to_def_id()) {
                 Ok(()) => {}
                 Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => {
                     let mut err = struct_span_err!(
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index 3a290b7756e..6b995b97386 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -24,8 +24,7 @@ impl UnsafetyChecker<'tcx> {
         unsafety: hir::Unsafety,
         polarity: hir::ImplPolarity,
     ) {
-        let local_did = self.tcx.hir().local_def_id(item.hir_id);
-        if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) {
+        if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) {
             let trait_def = self.tcx.trait_def(trait_ref.def_id);
             let unsafe_attr = impl_generics.and_then(|generics| {
                 generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index e24aa7d76f1..fc8e50b4b65 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -229,14 +229,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
     let mut visitor = PlaceholderHirTyCollector::default();
     visitor.visit_item(item);
 
-    placeholder_type_error(
-        tcx,
-        Some(generics.span),
-        &generics.params[..],
-        visitor.0,
-        suggest,
-        None,
-    );
+    placeholder_type_error(tcx, Some(generics.span), generics.params, visitor.0, suggest, None);
 }
 
 impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
@@ -247,7 +240,7 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        convert_item(self.tcx, item.hir_id);
+        convert_item(self.tcx, item.item_id());
         reject_placeholder_type_signatures_in_item(self.tcx, item);
         intravisit::walk_item(self, item);
     }
@@ -281,12 +274,12 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        convert_trait_item(self.tcx, trait_item.hir_id);
+        convert_trait_item(self.tcx, trait_item.trait_item_id());
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        convert_impl_item(self.tcx, impl_item.hir_id);
+        convert_impl_item(self.tcx, impl_item.impl_item_id());
         intravisit::walk_impl_item(self, impl_item);
     }
 }
@@ -417,7 +410,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
                         | hir::ItemKind::Struct(_, generics)
                         | hir::ItemKind::Union(_, generics) => {
                             let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
-                            let (lt_sp, sugg) = match &generics.params[..] {
+                            let (lt_sp, sugg) = match generics.params {
                                 [] => (generics.span, format!("<{}>", lt_name)),
                                 [bound, ..] => {
                                     (bound.span.shrink_to_lo(), format!("{}, ", lt_name))
@@ -714,10 +707,10 @@ fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool
     }
 }
 
-fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
-    let it = tcx.hir().expect_item(item_id);
-    debug!("convert: item {} with id {}", it.ident, it.hir_id);
-    let def_id = tcx.hir().local_def_id(item_id);
+fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
+    let it = tcx.hir().item(item_id);
+    debug!("convert: item {} with id {}", it.ident, it.hir_id());
+    let def_id = item_id.def_id;
 
     match it.kind {
         // These don't define types.
@@ -728,12 +721,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
         hir::ItemKind::ForeignMod { items, .. } => {
             for item in items {
                 let item = tcx.hir().foreign_item(item.id);
-                let def_id = tcx.hir().local_def_id(item.hir_id);
-                tcx.ensure().generics_of(def_id);
-                tcx.ensure().type_of(def_id);
-                tcx.ensure().predicates_of(def_id);
+                tcx.ensure().generics_of(item.def_id);
+                tcx.ensure().type_of(item.def_id);
+                tcx.ensure().predicates_of(item.def_id);
                 if let hir::ForeignItemKind::Fn(..) = item.kind {
-                    tcx.ensure().fn_sig(def_id);
+                    tcx.ensure().fn_sig(item.def_id);
                 }
             }
         }
@@ -804,23 +796,22 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
     }
 }
 
-fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
-    let trait_item = tcx.hir().expect_trait_item(trait_item_id);
-    let def_id = tcx.hir().local_def_id(trait_item.hir_id);
-    tcx.ensure().generics_of(def_id);
+fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
+    let trait_item = tcx.hir().trait_item(trait_item_id);
+    tcx.ensure().generics_of(trait_item_id.def_id);
 
     match trait_item.kind {
         hir::TraitItemKind::Fn(..) => {
-            tcx.ensure().type_of(def_id);
-            tcx.ensure().fn_sig(def_id);
+            tcx.ensure().type_of(trait_item_id.def_id);
+            tcx.ensure().fn_sig(trait_item_id.def_id);
         }
 
         hir::TraitItemKind::Const(.., Some(_)) => {
-            tcx.ensure().type_of(def_id);
+            tcx.ensure().type_of(trait_item_id.def_id);
         }
 
         hir::TraitItemKind::Const(..) => {
-            tcx.ensure().type_of(def_id);
+            tcx.ensure().type_of(trait_item_id.def_id);
             // Account for `const C: _;`.
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
@@ -828,8 +819,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
         }
 
         hir::TraitItemKind::Type(_, Some(_)) => {
-            tcx.ensure().item_bounds(def_id);
-            tcx.ensure().type_of(def_id);
+            tcx.ensure().item_bounds(trait_item_id.def_id);
+            tcx.ensure().type_of(trait_item_id.def_id);
             // Account for `type T = _;`.
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
@@ -837,7 +828,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
         }
 
         hir::TraitItemKind::Type(_, None) => {
-            tcx.ensure().item_bounds(def_id);
+            tcx.ensure().item_bounds(trait_item_id.def_id);
             // #74612: Visit and try to find bad placeholders
             // even if there is no concrete type.
             let mut visitor = PlaceholderHirTyCollector::default();
@@ -847,15 +838,15 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
         }
     };
 
-    tcx.ensure().predicates_of(def_id);
+    tcx.ensure().predicates_of(trait_item_id.def_id);
 }
 
-fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
-    let def_id = tcx.hir().local_def_id(impl_item_id);
+fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
+    let def_id = impl_item_id.def_id;
     tcx.ensure().generics_of(def_id);
     tcx.ensure().type_of(def_id);
     tcx.ensure().predicates_of(def_id);
-    let impl_item = tcx.hir().expect_impl_item(impl_item_id);
+    let impl_item = tcx.hir().impl_item(impl_item_id);
     match impl_item.kind {
         hir::ImplItemKind::Fn(..) => {
             tcx.ensure().fn_sig(def_id);
@@ -1122,7 +1113,7 @@ fn super_predicates_that_define_assoc_type(
         let is_trait_alias = tcx.is_trait_alias(trait_def_id);
         let superbounds2 = icx.type_parameter_bounds_in_generics(
             generics,
-            item.hir_id,
+            item.hir_id(),
             self_param_ty,
             OnlySelfBounds(!is_trait_alias),
             assoc_name,
@@ -1446,12 +1437,12 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     //
                     // Something of a hack: use the node id for the trait, also as
                     // the node id for the Self type parameter.
-                    let param_id = item.hir_id;
+                    let param_id = item.def_id;
 
                     opt_self = Some(ty::GenericParamDef {
                         index: 0,
                         name: kw::SelfUpper,
-                        def_id: tcx.hir().local_def_id(param_id).to_def_id(),
+                        def_id: param_id.to_def_id(),
                         pure_wrt_drop: false,
                         kind: ty::GenericParamDefKind::Type {
                             has_default: false,
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 7fa58dcd5f4..a2aa3b308ec 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -582,26 +582,23 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
         }
         fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The opaque type itself or its children are not within its reveal scope.
-            if def_id.to_def_id() != self.def_id {
-                self.check(def_id);
+            if it.def_id.to_def_id() != self.def_id {
+                self.check(it.def_id);
                 intravisit::walk_item(self, it);
             }
         }
         fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
             // The opaque type itself or its children are not within its reveal scope.
-            if def_id.to_def_id() != self.def_id {
-                self.check(def_id);
+            if it.def_id.to_def_id() != self.def_id {
+                self.check(it.def_id);
                 intravisit::walk_impl_item(self, it);
             }
         }
         fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
             debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
-            self.check(def_id);
+            self.check(it.def_id);
             intravisit::walk_trait_item(self, it);
         }
     }
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index 0bdcbaac0e9..7713381e62e 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -59,7 +59,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
     // but it's one that we must perform earlier than the rest of
     // WfCheck.
     for &module in tcx.hir().krate().modules.keys() {
-        tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module));
+        tcx.ensure().check_mod_impl_wf(module);
     }
 }
 
@@ -81,11 +81,10 @@ struct ImplWfCheck<'tcx> {
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         if let hir::ItemKind::Impl(ref impl_) = item.kind {
-            let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
-            enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_.items);
+            enforce_impl_params_are_constrained(self.tcx, item.def_id, impl_.items);
             enforce_impl_items_are_distinct(self.tcx, impl_.items);
             if self.min_specialization {
-                check_min_specialization(self.tcx, impl_def_id.to_def_id(), item.span);
+                check_min_specialization(self.tcx, item.def_id.to_def_id(), item.span);
             }
         }
     }
@@ -131,7 +130,7 @@ fn enforce_impl_params_are_constrained(
     // Disallow unconstrained lifetimes, but only if they appear in assoc types.
     let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs
         .iter()
-        .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id))
+        .map(|item_ref| item_ref.id.def_id)
         .flat_map(|def_id| {
             let item = tcx.associated_item(def_id);
             match item.kind {
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 22d95b8bcc0..6ddc26efeae 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -369,7 +369,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
     tcx.sess.track_errors(|| {
         tcx.sess.time("type_collecting", || {
             for &module in tcx.hir().krate().modules.keys() {
-                tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
+                tcx.ensure().collect_mod_item_types(module);
             }
         });
     })?;
@@ -401,7 +401,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
     tcx.sess.time("item_types_checking", || {
         for &module in tcx.hir().krate().modules.keys() {
-            tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
+            tcx.ensure().check_mod_item_types(module);
         }
     });
 
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 02008e180b3..6e6ecf6a22b 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::Node;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -53,16 +52,10 @@ pub struct InferVisitor<'cx, 'tcx> {
 
 impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let item_did = self.tcx.hir().local_def_id(item.hir_id);
+        let item_did = item.def_id;
 
         debug!("InferVisitor::visit_item(item={:?})", item_did);
 
-        let hir_id = self.tcx.hir().local_def_id_to_hir_id(item_did);
-        let item = match self.tcx.hir().get(hir_id) {
-            Node::Item(item) => item,
-            _ => bug!(),
-        };
-
         let mut item_required_predicates = RequiredPredicates::default();
         match item.kind {
             hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) => {
diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs
index 56d42f756c4..d4bef0c409a 100644
--- a/compiler/rustc_typeck/src/outlives/test.rs
+++ b/compiler/rustc_typeck/src/outlives/test.rs
@@ -14,12 +14,10 @@ struct OutlivesTest<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
-
         // For unit testing: check for a special "rustc_outlives"
         // attribute and report an error with various results if found.
-        if self.tcx.has_attr(item_def_id.to_def_id(), sym::rustc_outlives) {
-            let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
+        if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_outlives) {
+            let inferred_outlives_of = self.tcx.inferred_outlives_of(item.def_id);
             struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit();
         }
     }
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index 4e53b8c3615..f5355ea042b 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -71,7 +71,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         match item.kind {
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                self.visit_node_helper(item.hir_id);
+                self.visit_node_helper(item.hir_id());
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
                     self.visit_node_helper(struct_def.ctor_hir_id().unwrap());
@@ -79,7 +79,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             }
 
             hir::ItemKind::Enum(ref enum_def, _) => {
-                self.visit_node_helper(item.hir_id);
+                self.visit_node_helper(item.hir_id());
 
                 for variant in enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.data {
@@ -89,7 +89,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
             }
 
             hir::ItemKind::Fn(..) => {
-                self.visit_node_helper(item.hir_id);
+                self.visit_node_helper(item.hir_id());
             }
 
             _ => {}
@@ -98,19 +98,19 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Fn(..) = trait_item.kind {
-            self.visit_node_helper(trait_item.hir_id);
+            self.visit_node_helper(trait_item.hir_id());
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Fn(..) = impl_item.kind {
-            self.visit_node_helper(impl_item.hir_id);
+            self.visit_node_helper(impl_item.hir_id());
         }
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
         if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-            self.visit_node_helper(foreign_item.hir_id);
+            self.visit_node_helper(foreign_item.hir_id());
         }
     }
 }
diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs
index 3b2a1c24ddd..5d5baf78d33 100644
--- a/compiler/rustc_typeck/src/variance/terms.rs
+++ b/compiler/rustc_typeck/src/variance/terms.rs
@@ -128,11 +128,11 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(item.hir_id));
+        debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(item.hir_id()));
 
         match item.kind {
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                self.add_inferreds_for_item(item.hir_id);
+                self.add_inferreds_for_item(item.hir_id());
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
                     self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
@@ -140,7 +140,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             }
 
             hir::ItemKind::Enum(ref enum_def, _) => {
-                self.add_inferreds_for_item(item.hir_id);
+                self.add_inferreds_for_item(item.hir_id());
 
                 for variant in enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.data {
@@ -150,7 +150,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
             }
 
             hir::ItemKind::Fn(..) => {
-                self.add_inferreds_for_item(item.hir_id);
+                self.add_inferreds_for_item(item.hir_id());
             }
 
             _ => {}
@@ -159,19 +159,19 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
         if let hir::TraitItemKind::Fn(..) = trait_item.kind {
-            self.add_inferreds_for_item(trait_item.hir_id);
+            self.add_inferreds_for_item(trait_item.hir_id());
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
         if let hir::ImplItemKind::Fn(..) = impl_item.kind {
-            self.add_inferreds_for_item(impl_item.hir_id);
+            self.add_inferreds_for_item(impl_item.hir_id());
         }
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
         if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-            self.add_inferreds_for_item(foreign_item.hir_id);
+            self.add_inferreds_for_item(foreign_item.hir_id());
         }
     }
 }
diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs
index d6e43b6d669..2a0d950c87d 100644
--- a/compiler/rustc_typeck/src/variance/test.rs
+++ b/compiler/rustc_typeck/src/variance/test.rs
@@ -14,12 +14,10 @@ struct VarianceTest<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let item_def_id = self.tcx.hir().local_def_id(item.hir_id);
-
         // For unit testing: check for a special "rustc_variance"
         // attribute and report an error with various results if found.
-        if self.tcx.has_attr(item_def_id.to_def_id(), sym::rustc_variance) {
-            let variances_of = self.tcx.variances_of(item_def_id);
+        if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_variance) {
+            let variances_of = self.tcx.variances_of(item.def_id);
             struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit();
         }
     }