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/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast/src/visit.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs58
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs19
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs254
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs55
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/pretty_clif.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs32
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/coverageinfo/map.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs170
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs143
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs16
-rw-r--r--compiler/rustc_driver/src/lib.rs3
-rw-r--r--compiler/rustc_driver/src/pretty.rs5
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0277.md10
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs12
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir/src/lang_items.rs11
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_incremental/src/assert_module_sources.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs58
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs5
-rw-r--r--compiler/rustc_interface/src/passes.rs21
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs12
-rw-r--r--compiler/rustc_interface/src/queries.rs4
-rw-r--r--compiler/rustc_interface/src/util.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs10
-rw-r--r--compiler/rustc_lint/src/levels.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs29
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs96
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs12
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs11
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs55
-rw-r--r--compiler/rustc_middle/src/middle/cstore.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs34
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs2
-rw-r--r--compiler/rustc_middle/src/mir/query.rs6
-rw-r--r--compiler/rustc_middle/src/query/mod.rs111
-rw-r--r--compiler/rustc_middle/src/ty/context.rs34
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs2
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs11
-rw-r--r--compiler/rustc_middle/src/ty/util.rs33
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/mod.rs2
-rw-r--r--compiler/rustc_mir/src/dataflow/move_paths/builder.rs5
-rw-r--r--compiler/rustc_mir/src/interpret/memory.rs89
-rw-r--r--compiler/rustc_mir/src/interpret/terminator.rs29
-rw-r--r--compiler/rustc_mir/src/interpret/validity.rs1
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs6
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/default.rs12
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/mod.rs14
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs12
-rw-r--r--compiler/rustc_mir/src/transform/coverage/debug.rs4
-rw-r--r--compiler/rustc_mir/src/transform/coverage/mod.rs69
-rw-r--r--compiler/rustc_mir/src/transform/coverage/query.rs4
-rw-r--r--compiler/rustc_mir/src/transform/coverage/spans.rs78
-rw-r--r--compiler/rustc_mir/src/transform/coverage/tests.rs6
-rw-r--r--compiler/rustc_mir/src/transform/early_otherwise_branch.rs5
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs9
-rw-r--r--compiler/rustc_mir/src/transform/simplify_try.rs5
-rw-r--r--compiler/rustc_mir/src/util/pretty.rs16
-rw-r--r--compiler/rustc_mir/src/util/spanview.rs14
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs63
-rw-r--r--compiler/rustc_parse/src/parser/item.rs32
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs13
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs13
-rw-r--r--compiler/rustc_passes/src/dead.rs55
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs18
-rw-r--r--compiler/rustc_passes/src/entry.rs10
-rw-r--r--compiler/rustc_passes/src/intrinsicck.rs43
-rw-r--r--compiler/rustc_passes/src/lang_items.rs136
-rw-r--r--compiler/rustc_passes/src/lib_features.rs8
-rw-r--r--compiler/rustc_passes/src/reachable.rs12
-rw-r--r--compiler/rustc_passes/src/stability.rs10
-rw-r--r--compiler/rustc_plugin_impl/src/build.rs38
-rw-r--r--compiler/rustc_privacy/src/lib.rs12
-rw-r--r--compiler/rustc_query_impl/src/keys.rs10
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs16
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs43
-rw-r--r--compiler/rustc_target/src/asm/mod.rs13
-rw-r--r--compiler/rustc_target/src/asm/powerpc.rs10
-rw-r--r--compiler/rustc_target/src/spec/windows_gnu_base.rs1
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs81
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs53
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs30
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs13
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs22
-rw-r--r--compiler/rustc_typeck/src/check/op.rs19
-rw-r--r--compiler/rustc_typeck/src/check/place_op.rs32
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs18
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs4
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs12
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs5
-rw-r--r--compiler/rustc_typeck/src/coherence/mod.rs6
-rw-r--r--compiler/rustc_typeck/src/lib.rs6
-rw-r--r--compiler/rustc_typeck/src/outlives/mod.rs8
-rw-r--r--compiler/rustc_typeck/src/variance/mod.rs7
130 files changed, 1586 insertions, 1249 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index fb012d9802f..b3bac1d7ecd 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1861,6 +1861,10 @@ pub enum TyKind {
     Never,
     /// A tuple (`(A, B, C, D,...)`).
     Tup(Vec<P<Ty>>),
+    /// An anonymous struct type i.e. `struct { foo: Type }`
+    AnonymousStruct(Vec<FieldDef>, bool),
+    /// An anonymous union type i.e. `union { bar: Type }`
+    AnonymousUnion(Vec<FieldDef>, bool),
     /// A path (`module::module::...::Type`), optionally
     /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
     ///
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 374a6ec972f..071d41ea2b2 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -484,6 +484,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
         TyKind::MacCall(mac) => vis.visit_mac_call(mac),
+        TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => {
+            fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
+        }
     }
     vis.visit_span(span);
     visit_lazy_tts(tokens, vis);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index c50b334d3e9..f1a99bc51c9 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -404,6 +404,9 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
         TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
+        TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
+            walk_list!(visitor, visit_field_def, fields)
+        }
         TyKind::Never | TyKind::CVarArgs => {}
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 483135ed3a3..866f2180bb6 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -560,8 +560,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         )
     }
 
-    /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
-    /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
+    /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
+    /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
     /// and save the block id to use it as a break target for desugaring of the `?` operator.
     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
         self.with_catch_scope(body.id, |this| {
@@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let ok_wrapped_span =
                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
 
-            // `::std::ops::Try::from_ok($tail_expr)`
+            // `::std::ops::Try::from_output($tail_expr)`
             block.expr = Some(this.wrap_in_try_constructor(
-                hir::LangItem::TryFromOk,
+                hir::LangItem::TryTraitFromOutput,
                 try_span,
                 tail_expr,
                 ok_wrapped_span,
@@ -1579,14 +1579,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
             self.allow_try_trait.clone(),
         );
 
-        // `Try::into_result(<expr>)`
+        // `Try::branch(<expr>)`
         let scrutinee = {
             // expand <expr>
             let sub_expr = self.lower_expr_mut(sub_expr);
 
             self.expr_call_lang_item_fn(
                 unstable_span,
-                hir::LangItem::TryIntoResult,
+                hir::LangItem::TryTraitBranch,
                 arena_vec![self; sub_expr],
             )
         };
@@ -1604,8 +1604,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let attrs = vec![attr];
 
-        // `Ok(val) => #[allow(unreachable_code)] val,`
-        let ok_arm = {
+        // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
+        let continue_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
             let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
@@ -1614,27 +1614,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 val_pat_nid,
                 ThinVec::from(attrs.clone()),
             ));
-            let ok_pat = self.pat_ok(span, val_pat);
-            self.arm(ok_pat, val_expr)
+            let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
+            self.arm(continue_pat, val_expr)
         };
 
-        // `Err(err) => #[allow(unreachable_code)]
-        //              return Try::from_error(From::from(err)),`
-        let err_arm = {
-            let err_ident = Ident::with_dummy_span(sym::err);
-            let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
-            let from_expr = {
-                let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
-                self.expr_call_lang_item_fn(
-                    try_span,
-                    hir::LangItem::FromFrom,
-                    arena_vec![self; err_expr],
-                )
-            };
-            let from_err_expr = self.wrap_in_try_constructor(
-                hir::LangItem::TryFromError,
-                unstable_span,
-                from_expr,
+        // `ControlFlow::Break(residual) =>
+        //     #[allow(unreachable_code)]
+        //     return Try::from_residual(residual),`
+        let break_arm = {
+            let residual_ident = Ident::with_dummy_span(sym::residual);
+            let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
+            let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
+            let from_residual_expr = self.wrap_in_try_constructor(
+                hir::LangItem::TryTraitFromResidual,
+                try_span,
+                self.arena.alloc(residual_expr),
                 unstable_span,
             );
             let thin_attrs = ThinVec::from(attrs);
@@ -1645,25 +1639,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     try_span,
                     hir::ExprKind::Break(
                         hir::Destination { label: None, target_id },
-                        Some(from_err_expr),
+                        Some(from_residual_expr),
                     ),
                     thin_attrs,
                 ))
             } else {
                 self.arena.alloc(self.expr(
                     try_span,
-                    hir::ExprKind::Ret(Some(from_err_expr)),
+                    hir::ExprKind::Ret(Some(from_residual_expr)),
                     thin_attrs,
                 ))
             };
 
-            let err_pat = self.pat_err(try_span, err_local);
-            self.arm(err_pat, ret_expr)
+            let break_pat = self.pat_cf_break(try_span, residual_local);
+            self.arm(break_pat, ret_expr)
         };
 
         hir::ExprKind::Match(
             scrutinee,
-            arena_vec![self; err_arm, ok_arm],
+            arena_vec![self; break_arm, continue_arm],
             hir::MatchSource::TryDesugar,
         )
     }
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index aa236a690ec..292643d6d75 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -789,7 +789,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
+    pub(super) fn lower_field_def(
+        &mut self,
+        (index, f): (usize, &FieldDef),
+    ) -> hir::FieldDef<'hir> {
         let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
             let t = self.lower_path_ty(
                 &f.ty,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0439de0ee7b..56f97054f96 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -332,7 +332,7 @@ pub fn lower_crate<'a, 'hir>(
         lifetimes_to_define: Vec::new(),
         is_collecting_in_band_lifetimes: false,
         in_scope_lifetimes: Vec::new(),
-        allow_try_trait: Some([sym::try_trait][..].into()),
+        allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
     }
     .lower_crate(krate)
@@ -1267,6 +1267,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let kind = match t.kind {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
+            // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
+            TyKind::AnonymousStruct(ref _fields, _recovered) => {
+                self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit();
+                hir::TyKind::Err
+            }
+            TyKind::AnonymousUnion(ref _fields, _recovered) => {
+                self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit();
+                hir::TyKind::Err
+            }
             TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
@@ -2481,14 +2490,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.pat(span, hir::PatKind::Lit(expr))
     }
 
-    fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+    fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
         let field = self.single_pat_field(span, pat);
-        self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field)
+        self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field)
     }
 
-    fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+    fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
         let field = self.single_pat_field(span, pat);
-        self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field)
+        self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field)
     }
 
     fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 6d6438920c0..ba2da769497 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -175,10 +175,30 @@ impl<'a> AstValidator<'a> {
                     }
                 }
             }
+            TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
+                self.with_banned_assoc_ty_bound(|this| {
+                    walk_list!(this, visit_struct_field_def, fields)
+                });
+            }
             _ => visit::walk_ty(self, t),
         }
     }
 
+    fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
+        if let Some(ident) = field.ident {
+            if ident.name == kw::Underscore {
+                self.check_anonymous_field(field);
+                self.visit_vis(&field.vis);
+                self.visit_ident(ident);
+                self.visit_ty_common(&field.ty);
+                self.walk_ty(&field.ty);
+                walk_list!(self, visit_attribute, &field.attrs);
+                return;
+            }
+        }
+        self.visit_field_def(field);
+    }
+
     fn err_handler(&self) -> &rustc_errors::Handler {
         &self.session.diagnostic()
     }
@@ -213,6 +233,66 @@ impl<'a> AstValidator<'a> {
         err.emit();
     }
 
+    fn check_anonymous_field(&self, field: &FieldDef) {
+        let FieldDef { ty, .. } = field;
+        match &ty.kind {
+            TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
+                // We already checked for `kw::Underscore` before calling this function,
+                // so skip the check
+            }
+            TyKind::Path(..) => {
+                // If the anonymous field contains a Path as type, we can't determine
+                // if the path is a valid struct or union, so skip the check
+            }
+            _ => {
+                let msg = "unnamed fields can only have struct or union types";
+                let label = "not a struct or union";
+                self.err_handler()
+                    .struct_span_err(field.span, msg)
+                    .span_label(ty.span, label)
+                    .emit();
+            }
+        }
+    }
+
+    fn deny_anonymous_struct(&self, ty: &Ty) {
+        match &ty.kind {
+            TyKind::AnonymousStruct(..) => {
+                self.err_handler()
+                    .struct_span_err(
+                        ty.span,
+                        "anonymous structs are not allowed outside of unnamed struct or union fields",
+                    )
+                    .span_label(ty.span, "anonymous struct declared here")
+                    .emit();
+            }
+            TyKind::AnonymousUnion(..) => {
+                self.err_handler()
+                    .struct_span_err(
+                        ty.span,
+                        "anonymous unions are not allowed outside of unnamed struct or union fields",
+                    )
+                    .span_label(ty.span, "anonymous union declared here")
+                    .emit();
+            }
+            _ => {}
+        }
+    }
+
+    fn deny_anonymous_field(&self, field: &FieldDef) {
+        if let Some(ident) = field.ident {
+            if ident.name == kw::Underscore {
+                self.err_handler()
+                    .struct_span_err(
+                        field.span,
+                        "anonymous fields are not allowed outside of structs or unions",
+                    )
+                    .span_label(ident.span, "anonymous field declared here")
+                    .emit()
+            }
+        }
+    }
+
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
@@ -732,6 +812,71 @@ impl<'a> AstValidator<'a> {
             )
             .emit();
     }
+
+    fn visit_ty_common(&mut self, ty: &'a Ty) {
+        match ty.kind {
+            TyKind::BareFn(ref bfty) => {
+                self.check_fn_decl(&bfty.decl, SelfSemantic::No);
+                Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
+                    struct_span_err!(
+                        self.session,
+                        span,
+                        E0561,
+                        "patterns aren't allowed in function pointer types"
+                    )
+                    .emit();
+                });
+                self.check_late_bound_lifetime_defs(&bfty.generic_params);
+            }
+            TyKind::TraitObject(ref bounds, ..) => {
+                let mut any_lifetime_bounds = false;
+                for bound in bounds {
+                    if let GenericBound::Outlives(ref lifetime) = *bound {
+                        if any_lifetime_bounds {
+                            struct_span_err!(
+                                self.session,
+                                lifetime.ident.span,
+                                E0226,
+                                "only a single explicit lifetime bound is permitted"
+                            )
+                            .emit();
+                            break;
+                        }
+                        any_lifetime_bounds = true;
+                    }
+                }
+                self.no_questions_in_bounds(bounds, "trait object types", false);
+            }
+            TyKind::ImplTrait(_, ref bounds) => {
+                if self.is_impl_trait_banned {
+                    struct_span_err!(
+                        self.session,
+                        ty.span,
+                        E0667,
+                        "`impl Trait` is not allowed in path parameters"
+                    )
+                    .emit();
+                }
+
+                if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
+                    struct_span_err!(
+                        self.session,
+                        ty.span,
+                        E0666,
+                        "nested `impl Trait` is not allowed"
+                    )
+                    .span_label(outer_impl_trait_sp, "outer `impl Trait`")
+                    .span_label(ty.span, "nested `impl Trait` here")
+                    .emit();
+                }
+
+                if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
+                    self.err_handler().span_err(ty.span, "at least one trait must be specified");
+                }
+            }
+            _ => {}
+        }
+    }
 }
 
 /// Checks that generic parameters are in the correct order,
@@ -850,72 +995,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
-        match ty.kind {
-            TyKind::BareFn(ref bfty) => {
-                self.check_fn_decl(&bfty.decl, SelfSemantic::No);
-                Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
-                    struct_span_err!(
-                        self.session,
-                        span,
-                        E0561,
-                        "patterns aren't allowed in function pointer types"
-                    )
-                    .emit();
-                });
-                self.check_late_bound_lifetime_defs(&bfty.generic_params);
-            }
-            TyKind::TraitObject(ref bounds, ..) => {
-                let mut any_lifetime_bounds = false;
-                for bound in bounds {
-                    if let GenericBound::Outlives(ref lifetime) = *bound {
-                        if any_lifetime_bounds {
-                            struct_span_err!(
-                                self.session,
-                                lifetime.ident.span,
-                                E0226,
-                                "only a single explicit lifetime bound is permitted"
-                            )
-                            .emit();
-                            break;
-                        }
-                        any_lifetime_bounds = true;
-                    }
-                }
-                self.no_questions_in_bounds(bounds, "trait object types", false);
-            }
-            TyKind::ImplTrait(_, ref bounds) => {
-                if self.is_impl_trait_banned {
-                    struct_span_err!(
-                        self.session,
-                        ty.span,
-                        E0667,
-                        "`impl Trait` is not allowed in path parameters"
-                    )
-                    .emit();
-                }
-
-                if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
-                    struct_span_err!(
-                        self.session,
-                        ty.span,
-                        E0666,
-                        "nested `impl Trait` is not allowed"
-                    )
-                    .span_label(outer_impl_trait_sp, "outer `impl Trait`")
-                    .span_label(ty.span, "nested `impl Trait` here")
-                    .emit();
-                }
-
-                if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
-                    self.err_handler().span_err(ty.span, "at least one trait must be specified");
-                }
-
-                self.walk_ty(ty);
-                return;
-            }
-            _ => {}
-        }
-
+        self.visit_ty_common(ty);
+        self.deny_anonymous_struct(ty);
         self.walk_ty(ty)
     }
 
@@ -929,6 +1010,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_lifetime(self, lifetime);
     }
 
+    fn visit_field_def(&mut self, s: &'a FieldDef) {
+        self.deny_anonymous_field(s);
+        visit::walk_field_def(self, s)
+    }
+
     fn visit_item(&mut self, item: &'a Item) {
         if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) {
             self.has_proc_macro_decls = true;
@@ -1084,14 +1170,42 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.check_mod_file_item_asciionly(item.ident);
                 }
             }
-            ItemKind::Union(ref vdata, _) => {
-                if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
-                    self.err_handler()
-                        .span_err(item.span, "tuple and unit unions are not permitted");
+            ItemKind::Struct(ref vdata, ref generics) => match vdata {
+                // Duplicating the `Visitor` logic allows catching all cases
+                // of `Anonymous(Struct, Union)` outside of a field struct or union.
+                //
+                // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
+                // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
+                // it uses `visit_ty_common`, which doesn't contain that specific check.
+                VariantData::Struct(ref fields, ..) => {
+                    self.visit_vis(&item.vis);
+                    self.visit_ident(item.ident);
+                    self.visit_generics(generics);
+                    self.with_banned_assoc_ty_bound(|this| {
+                        walk_list!(this, visit_struct_field_def, fields);
+                    });
+                    walk_list!(self, visit_attribute, &item.attrs);
+                    return;
                 }
+                _ => {}
+            },
+            ItemKind::Union(ref vdata, ref generics) => {
                 if vdata.fields().is_empty() {
                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
                 }
+                match vdata {
+                    VariantData::Struct(ref fields, ..) => {
+                        self.visit_vis(&item.vis);
+                        self.visit_ident(item.ident);
+                        self.visit_generics(generics);
+                        self.with_banned_assoc_ty_bound(|this| {
+                            walk_list!(this, visit_struct_field_def, fields);
+                        });
+                        walk_list!(self, visit_attribute, &item.attrs);
+                        return;
+                    }
+                    _ => {}
+                }
             }
             ItemKind::Const(def, .., None) => {
                 self.check_defaultness(item.span, def);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index dc3383dae84..4996c2195ef 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -713,10 +713,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
     gate_all!(inline_const, "inline-const is experimental");
     gate_all!(
-        extended_key_value_attributes,
-        "arbitrary expressions in key-value attributes are unstable"
-    );
-    gate_all!(
         const_generics_defaults,
         "default values for const generic parameters are experimental"
     );
@@ -725,6 +721,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
         // involved, so we only emit errors where there are no other parsing errors.
         gate_all!(destructuring_assignment, "destructuring assignments are unstable");
     }
+    gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 0e42e0e3793..da9d89745a8 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -140,12 +140,15 @@ pub fn print_crate<'a>(
 // and also addresses some specific regressions described in #63896 and #73345.
 fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     if let TokenTree::Token(token) = prev {
+        if matches!(token.kind, token::Dot) {
+            return false;
+        }
         if let token::DocComment(comment_kind, ..) = token.kind {
             return comment_kind != CommentKind::Line;
         }
     }
     match tt {
-        TokenTree::Token(token) => token.kind != token::Comma,
+        TokenTree::Token(token) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
         TokenTree::Delimited(_, DelimToken::Paren, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }))
         }
@@ -951,6 +954,14 @@ impl<'a> State<'a> {
                 }
                 self.pclose();
             }
+            ast::TyKind::AnonymousStruct(ref fields, ..) => {
+                self.s.word("struct");
+                self.print_record_struct_body(fields, ty.span);
+            }
+            ast::TyKind::AnonymousUnion(ref fields, ..) => {
+                self.s.word("union");
+                self.print_record_struct_body(fields, ty.span);
+            }
             ast::TyKind::Paren(ref typ) => {
                 self.popen();
                 self.print_type(typ);
@@ -1386,6 +1397,29 @@ impl<'a> State<'a> {
         }
     }
 
+    crate fn print_record_struct_body(
+        &mut self,
+        fields: &Vec<ast::FieldDef>,
+        span: rustc_span::Span,
+    ) {
+        self.nbsp();
+        self.bopen();
+        self.hardbreak_if_not_bol();
+
+        for field in fields {
+            self.hardbreak_if_not_bol();
+            self.maybe_print_comment(field.span.lo());
+            self.print_outer_attributes(&field.attrs);
+            self.print_visibility(&field.vis);
+            self.print_ident(field.ident.unwrap());
+            self.word_nbsp(":");
+            self.print_type(&field.ty);
+            self.s.word(",");
+        }
+
+        self.bclose(span)
+    }
+
     crate fn print_struct(
         &mut self,
         struct_def: &ast::VariantData,
@@ -1415,24 +1449,9 @@ impl<'a> State<'a> {
                 self.end();
                 self.end(); // Close the outer-box.
             }
-            ast::VariantData::Struct(..) => {
+            ast::VariantData::Struct(ref fields, ..) => {
                 self.print_where_clause(&generics.where_clause);
-                self.nbsp();
-                self.bopen();
-                self.hardbreak_if_not_bol();
-
-                for field in struct_def.fields() {
-                    self.hardbreak_if_not_bol();
-                    self.maybe_print_comment(field.span.lo());
-                    self.print_outer_attributes(&field.attrs);
-                    self.print_visibility(&field.vis);
-                    self.print_ident(field.ident.unwrap());
-                    self.word_nbsp(":");
-                    self.print_type(&field.ty);
-                    self.s.word(",");
-                }
-
-                self.bclose(span)
+                self.print_record_struct_body(fields, span);
             }
         }
     }
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index a09e3257786..357a9f2daf7 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -13,7 +13,7 @@ pub(crate) fn codegen(
     module: &mut impl Module,
     unwind_context: &mut UnwindContext,
 ) -> bool {
-    let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE).iter().any(|(_, list)| {
+    let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
         use rustc_middle::middle::dependency_format::Linkage;
         list.iter().any(|&linkage| linkage == Linkage::Dynamic)
     });
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 004e6bddaf3..24d933728db 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -42,7 +42,7 @@ fn emit_module(
 
     unwind_context.emit(&mut product);
 
-    let tmp_file = tcx.output_filenames(LOCAL_CRATE).temp_path(OutputType::Object, Some(&name));
+    let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name));
     let obj = product.object.write().unwrap();
     if let Err(err) = std::fs::write(&tmp_file, obj) {
         tcx.sess.fatal(&format!("error writing object file: {}", err));
@@ -74,7 +74,7 @@ fn reuse_workproduct_for_cgu(
     let work_product = cgu.work_product(tcx);
     if let Some(saved_file) = &work_product.saved_file {
         let obj_out = tcx
-            .output_filenames(LOCAL_CRATE)
+            .output_filenames(())
             .temp_path(OutputType::Object, Some(&cgu.name().as_str()));
         object = Some(obj_out.clone());
         let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
@@ -190,7 +190,7 @@ pub(crate) fn run_aot(
     let mut work_products = FxHashMap::default();
 
     let cgus = if tcx.sess.opts.output_types.should_codegen() {
-        tcx.collect_and_partition_mono_items(LOCAL_CRATE).1
+        tcx.collect_and_partition_mono_items(()).1
     } else {
         // If only `--emit metadata` is used, we shouldn't perform any codegen.
         // Also `tcx.collect_and_partition_mono_items` may panic in that case.
@@ -276,7 +276,7 @@ pub(crate) fn run_aot(
                 .to_string();
 
             let tmp_file = tcx
-                .output_filenames(LOCAL_CRATE)
+                .output_filenames(())
                 .temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
 
             let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| {
@@ -353,7 +353,7 @@ fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) {
         .join("\n");
 
     let output_object_file =
-        tcx.output_filenames(LOCAL_CRATE).temp_path(OutputType::Object, Some(cgu_name));
+        tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name));
 
     // Assemble `global_asm`
     let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 53c93f6a9dd..632e86da736 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -8,7 +8,6 @@ use std::os::raw::{c_char, c_int};
 use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
 use rustc_codegen_ssa::CrateInfo;
 use rustc_middle::mir::mono::MonoItem;
-use rustc_session::config::EntryFnType;
 
 use cranelift_jit::{JITBuilder, JITModule};
 
@@ -66,7 +65,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         matches!(backend_config.codegen_mode, CodegenMode::JitLazy),
     );
 
-    let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+    let (_, cgus) = tcx.collect_and_partition_mono_items(());
     let mono_items = cgus
         .iter()
         .map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
@@ -179,7 +178,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
     let mut dylib_paths = Vec::new();
 
     let crate_info = CrateInfo::new(tcx);
-    let formats = tcx.dependency_formats(LOCAL_CRATE);
+    let formats = tcx.dependency_formats(());
     let data = &formats
         .iter()
         .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index d504024a335..d1958c5f96b 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -15,7 +15,7 @@ pub(crate) fn maybe_create_entry_wrapper(
     unwind_context: &mut UnwindContext,
     is_jit: bool,
 ) {
-    let (main_def_id, is_main_fn) = match tcx.entry_fn(LOCAL_CRATE) {
+    let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
         Some((def_id, entry_ty)) => (
             def_id,
             match entry_ty {
diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
index 158811c5eaf..cd8c5b51608 100644
--- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
@@ -214,7 +214,7 @@ pub(crate) fn write_ir_file(
         return;
     }
 
-    let clif_output_dir = tcx.output_filenames(LOCAL_CRATE).with_extension("clif");
+    let clif_output_dir = tcx.output_filenames(()).with_extension("clif");
 
     match std::fs::create_dir(&clif_output_dir) {
         Ok(()) => {}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index a571418c1f5..0aef77129d8 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -283,7 +283,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 }
                 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
                 InlineAsmArch::Nvptx64 => {}
-                InlineAsmArch::PowerPC => {}
+                InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
                 InlineAsmArch::Hexagon => {}
                 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
                 InlineAsmArch::SpirV => {}
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 4219797c5cd..5b4a187a1d5 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -20,7 +20,6 @@ use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_errors::{FatalError, Handler, Level};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath};
@@ -92,13 +91,12 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm:
 
 pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
     let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() {
-        tcx.output_filenames(LOCAL_CRATE)
-            .split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name))
+        tcx.output_filenames(()).split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name))
     } else {
         None
     };
     let config = TargetMachineFactoryConfig { split_dwarf_file };
-    target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))(config)
+    target_machine_factory(&tcx.sess, tcx.backend_optimization_level(()))(config)
         .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 053cda1e7cc..bc9d99ed4a1 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -118,24 +118,16 @@ macro_rules! builder_methods_for_value_instructions {
 }
 
 impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
-    fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self {
-        let mut bx = Builder::with_cx(cx);
-        let llbb = unsafe {
-            let name = SmallCStr::new(name);
-            llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr())
-        };
-        bx.position_at_end(llbb);
+    fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self {
+        let bx = Builder::with_cx(cx);
+        unsafe {
+            llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
+        }
         bx
     }
 
-    fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
-        // Create a fresh builder from the crate context.
-        let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) };
-        Builder { llbuilder, cx }
-    }
-
-    fn build_sibling_block(&self, name: &str) -> Self {
-        Builder::new_block(self.cx, self.llfn(), name)
+    fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
+        self.cx
     }
 
     fn llbb(&self) -> &'ll BasicBlock {
@@ -144,12 +136,22 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn set_span(&mut self, _span: Span) {}
 
-    fn position_at_end(&mut self, llbb: &'ll BasicBlock) {
+    fn append_block(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &str) -> &'ll BasicBlock {
         unsafe {
-            llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
+            let name = SmallCStr::new(name);
+            llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr())
         }
     }
 
+    fn append_sibling_block(&mut self, name: &str) -> &'ll BasicBlock {
+        Self::append_block(self.cx, self.llfn(), name)
+    }
+
+    fn build_sibling_block(&mut self, name: &str) -> Self {
+        let llbb = self.append_sibling_block(name);
+        Self::build(self.cx, llbb)
+    }
+
     fn ret_void(&mut self) {
         unsafe {
             llvm::LLVMBuildRetVoid(self.llbuilder);
@@ -1144,14 +1146,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
     }
 
-    fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
-        self.cx
-    }
-
-    unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) {
-        llvm::LLVMDeleteBasicBlock(bb);
-    }
-
     fn do_not_inline(&mut self, llret: &'ll Value) {
         llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
     }
@@ -1165,6 +1159,12 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
 }
 
 impl Builder<'a, 'll, 'tcx> {
+    fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
+        // Create a fresh builder from the crate context.
+        let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) };
+        Builder { llbuilder, cx }
+    }
+
     pub fn llfn(&self) -> &'ll Value {
         unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) }
     }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 30f125ca3be..d2a2e739ff3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -6,7 +6,7 @@ use llvm::coverageinfo::CounterMappingRegion;
 use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
 use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_llvm::RustString;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_span::Symbol;
@@ -265,7 +265,7 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
     let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics();
 
     let all_def_ids: DefIdSet = tcx
-        .mir_keys(LOCAL_CRATE)
+        .mir_keys(())
         .iter()
         .filter_map(|local_def_id| {
             let def_id = local_def_id.to_def_id();
@@ -276,7 +276,7 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
         })
         .collect();
 
-    let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE);
+    let codegenned_def_ids = tcx.codegened_and_inlined_items(());
 
     let mut unused_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default();
     for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index afc2bdbfd52..019bf4a09a7 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -223,7 +223,8 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
 
 fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) {
     let llfn = cx.get_fn(instance);
-    let mut bx = Builder::new_block(cx, llfn, "unused_function");
+    let llbb = Builder::append_block(cx, llfn, "unused_function");
+    let mut bx = Builder::build(cx, llbb);
     let fn_name = bx.get_pgo_func_name_var(instance);
     let hash = bx.const_u64(0);
     let num_counters = bx.const_u32(1);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 5cf831475d4..0db6659f8e2 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -995,9 +995,10 @@ pub fn compile_unit_metadata(
     let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
     let work_dir = tcx.sess.working_dir.to_string_lossy(false);
     let flags = "\0";
-    let out_dir = &tcx.output_filenames(LOCAL_CRATE).out_directory;
+    let output_filenames = tcx.output_filenames(());
+    let out_dir = &output_filenames.out_directory;
     let split_name = if tcx.sess.target_can_use_split_dwarf() {
-        tcx.output_filenames(LOCAL_CRATE)
+        output_filenames
             .split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name))
             .map(|f| out_dir.join(f))
     } else {
@@ -1058,15 +1059,12 @@ pub fn compile_unit_metadata(
         if tcx.sess.opts.debugging_opts.profile {
             let cu_desc_metadata =
                 llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
-            let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda");
+            let default_gcda_path = &output_filenames.with_extension("gcda");
             let gcda_path =
                 tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
 
             let gcov_cu_info = [
-                path_to_mdstring(
-                    debug_context.llcontext,
-                    &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"),
-                ),
+                path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
                 path_to_mdstring(debug_context.llcontext, &gcda_path),
                 cu_desc_metadata,
             ];
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index b928e903730..2b99a2ebad9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -23,7 +23,7 @@ use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, Variab
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir;
 use rustc_middle::ty::layout::HasTyCtxt;
@@ -343,7 +343,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         if self.sess().opts.optimize != config::OptLevel::No {
             spflags |= DISPFlags::SPFlagOptimized;
         }
-        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
+        if let Some((id, _)) = self.tcx.entry_fn(()) {
             if id == def_id {
                 spflags |= DISPFlags::SPFlagMainSubprogram;
             }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index fc6c1abf4af..22d513d66d1 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -678,7 +678,8 @@ fn gen_fn<'ll, 'tcx>(
     cx.apply_target_cpu_attr(llfn);
     // FIXME(eddyb) find a nicer way to do this.
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
-    let bx = Builder::new_block(cx, llfn, "entry-block");
+    let llbb = Builder::append_block(cx, llfn, "entry-block");
+    let bx = Builder::build(cx, llbb);
     codegen(bx);
     llfn
 }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 329458773ff..8eef06f018f 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -8,7 +8,7 @@
 #![feature(bool_to_option)]
 #![feature(const_cstr_unchecked)]
 #![feature(crate_visibility_modifier)]
-#![feature(extended_key_value_attributes)]
+#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 32fdde9b42e..bf66040a7eb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1079,7 +1079,6 @@ extern "C" {
         Fn: &'a Value,
         Name: *const c_char,
     ) -> &'a BasicBlock;
-    pub fn LLVMDeleteBasicBlock(BB: &BasicBlock);
 
     // Operations on instructions
     pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 93059b2323d..4dc9a3f5e41 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -281,8 +281,11 @@ impl<'a> Linker for GccLinker<'a> {
                 }
             }
             LinkOutputKind::DynamicPicExe => {
-                // `-pie` works for both gcc wrapper and ld.
-                self.cmd.arg("-pie");
+                // noop on windows w/ gcc & ld, error w/ lld
+                if !self.sess.target.is_like_windows {
+                    // `-pie` works for both gcc wrapper and ld.
+                    self.cmd.arg("-pie");
+                }
             }
             LinkOutputKind::StaticNoPicExe => {
                 // `-static` works for both gcc wrapper and ld.
@@ -347,7 +350,7 @@ impl<'a> Linker for GccLinker<'a> {
                 // has -needed-l{} / -needed_library {}
                 // but we have no way to detect that here.
                 self.sess.warn("`as-needed` modifier not implemented yet for ld64");
-            } else if self.sess.target.linker_is_gnu {
+            } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
                 self.linker_arg("--no-as-needed");
             } else {
                 self.sess.warn("`as-needed` modifier not supported for current linker");
@@ -358,7 +361,7 @@ impl<'a> Linker for GccLinker<'a> {
         if !as_needed {
             if self.sess.target.is_like_osx {
                 // See above FIXME comment
-            } else if self.sess.target.linker_is_gnu {
+            } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
                 self.linker_arg("--as-needed");
             }
         }
@@ -469,7 +472,7 @@ impl<'a> Linker for GccLinker<'a> {
         // eliminate the metadata. If we're building an executable, however,
         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
         // reduction.
-        } else if !keep_metadata {
+        } else if self.sess.target.linker_is_gnu && !keep_metadata {
             self.linker_arg("--gc-sections");
         }
     }
@@ -477,9 +480,7 @@ impl<'a> Linker for GccLinker<'a> {
     fn no_gc_sections(&mut self) {
         if self.sess.target.is_like_osx {
             self.linker_arg("-no_dead_strip");
-        } else if self.sess.target.is_like_solaris {
-            self.linker_arg("-zrecord");
-        } else {
+        } else if self.sess.target.linker_is_gnu {
             self.linker_arg("--no-gc-sections");
         }
     }
@@ -692,7 +693,7 @@ impl<'a> Linker for GccLinker<'a> {
     }
 
     fn add_as_needed(&mut self) {
-        if self.sess.target.linker_is_gnu {
+        if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
             self.linker_arg("--as-needed");
         } else if self.sess.target.is_like_solaris {
             // -z ignore is the Solaris equivalent to the GNU ld --as-needed option
@@ -1303,7 +1304,7 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
         }
     }
 
-    let formats = tcx.dependency_formats(LOCAL_CRATE);
+    let formats = tcx.dependency_formats(());
     let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap();
 
     for (index, dep_format) in deps.iter().enumerate() {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 2bff2fcba43..14d6f0ba147 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -4,7 +4,7 @@ use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -60,7 +60,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
         tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
 
     let mut reachable_non_generics: DefIdMap<_> = tcx
-        .reachable_set(LOCAL_CRATE)
+        .reachable_set(())
         .iter()
         .filter_map(|&def_id| {
             // We want to ignore some FFI functions that are not exposed from
@@ -133,12 +133,12 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
         })
         .collect();
 
-    if let Some(id) = tcx.proc_macro_decls_static(LOCAL_CRATE) {
-        reachable_non_generics.insert(id, SymbolExportLevel::C);
+    if let Some(id) = tcx.proc_macro_decls_static(()) {
+        reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C);
     }
 
-    if let Some(id) = tcx.plugin_registrar_fn(LOCAL_CRATE) {
-        reachable_non_generics.insert(id, SymbolExportLevel::C);
+    if let Some(id) = tcx.plugin_registrar_fn(()) {
+        reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C);
     }
 
     reachable_non_generics
@@ -174,7 +174,7 @@ fn exported_symbols_provider_local(
         .map(|(&def_id, &level)| (ExportedSymbol::NonGeneric(def_id), level))
         .collect();
 
-    if tcx.entry_fn(LOCAL_CRATE).is_some() {
+    if tcx.entry_fn(()).is_some() {
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, "main"));
 
         symbols.push((exported_symbol, SymbolExportLevel::C));
@@ -230,7 +230,7 @@ fn exported_symbols_provider_local(
         // external linkage is enough for monomorphization to be linked to.
         let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib;
 
-        let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+        let (_, cgus) = tcx.collect_and_partition_mono_items(());
 
         for (mono_item, &(linkage, visibility)) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
             if linkage != Linkage::External {
@@ -275,11 +275,9 @@ fn exported_symbols_provider_local(
 
 fn upstream_monomorphizations_provider(
     tcx: TyCtxt<'_>,
-    cnum: CrateNum,
+    (): (),
 ) -> DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
-    debug_assert!(cnum == LOCAL_CRATE);
-
-    let cnums = tcx.all_crate_nums(LOCAL_CRATE);
+    let cnums = tcx.all_crate_nums(());
 
     let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
 
@@ -341,7 +339,7 @@ fn upstream_monomorphizations_for_provider(
     def_id: DefId,
 ) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
     debug_assert!(!def_id.is_local());
-    tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
+    tcx.upstream_monomorphizations(()).get(&def_id)
 }
 
 fn upstream_drop_glue_for_provider<'tcx>(
@@ -355,12 +353,8 @@ fn upstream_drop_glue_for_provider<'tcx>(
     }
 }
 
-fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    if let Some(def_id) = def_id.as_local() {
-        !tcx.reachable_set(LOCAL_CRATE).contains(&def_id)
-    } else {
-        bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
-    }
+fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+    !tcx.reachable_set(()).contains(&def_id)
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index fb0662a3993..49774dc6d5c 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -482,7 +482,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
         codegen_worker_receive,
         shared_emitter_main,
         future: coordinator_thread,
-        output_filenames: tcx.output_filenames(LOCAL_CRATE),
+        output_filenames: tcx.output_filenames(()),
     }
 }
 
@@ -1042,7 +1042,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         // If we know that we won’t be doing codegen, create target machines without optimisation.
         config::OptLevel::No
     } else {
-        tcx.backend_optimization_level(LOCAL_CRATE)
+        tcx.backend_optimization_level(())
     };
     let cgcx = CodegenContext::<B> {
         backend: backend.clone(),
@@ -1061,7 +1061,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
         coordinator_send,
         diag_emitter: shared_emitter.clone(),
-        output_filenames: tcx.output_filenames(LOCAL_CRATE),
+        output_filenames: tcx.output_filenames(()),
         regular_module_config: regular_config,
         metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index a9ab075d3db..b44e74d5ae8 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -347,7 +347,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
 ) -> Option<Bx::Function> {
-    let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?;
+    let (main_def_id, entry_type) = cx.tcx().entry_fn(())?;
     let main_is_local = main_def_id.is_local();
     let instance = Instance::mono(cx.tcx(), main_def_id);
 
@@ -364,10 +364,9 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     let main_llfn = cx.get_fn_addr(instance);
 
-    return cx.tcx().entry_fn(LOCAL_CRATE).map(|(_, et)| {
-        let use_start_lang_item = EntryFnType::Start != et;
-        create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item)
-    });
+    let use_start_lang_item = EntryFnType::Start != entry_type;
+    let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item);
+    return Some(entry_fn);
 
     fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         cx: &'a Bx::CodegenCx,
@@ -409,7 +408,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         cx.set_frame_pointer_elimination(llfn);
         cx.apply_target_cpu_attr(llfn);
 
-        let mut bx = Bx::new_block(&cx, llfn, "top");
+        let llbb = Bx::append_block(&cx, llfn, "top");
+        let mut bx = Bx::build(&cx, llbb);
 
         bx.insert_reference_to_gdb_debug_scripts_section_global();
 
@@ -486,7 +486,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
     // Run the monomorphization collector and partition the collected items into
     // codegen units.
-    let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
+    let codegen_units = tcx.collect_and_partition_mono_items(()).1;
 
     // Force all codegen_unit queries so they are already either red or green
     // when compile_codegen_unit accesses them. We are not able to re-execute
@@ -511,7 +511,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     // linkage, then it's already got an allocator shim and we'll be using that
     // one instead. If nothing exists then it's our job to generate the
     // allocator!
-    let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE).iter().any(|(_, list)| {
+    let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
         use rustc_middle::middle::dependency_format::Linkage;
         list.iter().any(|&linkage| linkage == Linkage::Dynamic)
     });
@@ -768,7 +768,7 @@ impl CrateInfo {
             used_crate_source: Default::default(),
             lang_item_to_crate: Default::default(),
             missing_lang_items: Default::default(),
-            dependency_formats: tcx.dependency_formats(LOCAL_CRATE),
+            dependency_formats: tcx.dependency_formats(()),
         };
         let lang_items = tcx.lang_items();
 
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 955f658eb1c..1fa60612d26 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -219,8 +219,6 @@ pub fn asm_const_to_str<'tcx>(
             ty::IntTy::I128 => (value as i128).to_string(),
             ty::IntTy::Isize => unreachable!(),
         },
-        ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(),
-        ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(),
         _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
index 4458fd68678..08442c588f8 100644
--- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
+++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
@@ -49,9 +49,9 @@ impl<'tcx> FunctionCoverage<'tcx> {
     }
 
     fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self {
-        let coverageinfo = tcx.coverageinfo(instance.def_id());
+        let coverageinfo = tcx.coverageinfo(instance.def);
         debug!(
-            "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}. is_used={}",
+            "FunctionCoverage::create(instance={:?}) has coverageinfo={:?}. is_used={}",
             instance, coverageinfo, is_used
         );
         Self {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 2bd35fe9b14..93200bd1f26 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, LayoutOf};
+use rustc_target::abi::{self, HasDataLayout, LayoutOf};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -32,13 +32,34 @@ struct TerminatorCodegenHelper<'tcx> {
 }
 
 impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
-    /// Returns the associated funclet from `FunctionCx::funclets` for the
-    /// `funclet_bb` member if it is not `None`.
+    /// Returns the appropriate `Funclet` for the current funclet, if on MSVC,
+    /// either already previously cached, or newly created, by `landing_pad_for`.
     fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
         &self,
-        fx: &'b FunctionCx<'a, 'tcx, Bx>,
+        fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
     ) -> Option<&'b Bx::Funclet> {
-        self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref())
+        let funclet_bb = self.funclet_bb?;
+        if base::wants_msvc_seh(fx.cx.tcx().sess) {
+            // If `landing_pad_for` hasn't been called yet to create the `Funclet`,
+            // it has to be now. This may not seem necessary, as RPO should lead
+            // to all the unwind edges being visited (and so to `landing_pad_for`
+            // getting called for them), before building any of the blocks inside
+            // the funclet itself - however, if MIR contains edges that end up not
+            // being needed in the LLVM IR after monomorphization, the funclet may
+            // be unreachable, and we don't have yet a way to skip building it in
+            // such an eventuality (which may be a better solution than this).
+            if fx.funclets[funclet_bb].is_none() {
+                fx.landing_pad_for(funclet_bb);
+            }
+
+            Some(
+                fx.funclets[funclet_bb]
+                    .as_ref()
+                    .expect("landing_pad_for didn't also create funclets entry"),
+            )
+        } else {
+            None
+        }
     }
 
     fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
@@ -47,17 +68,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         target: mir::BasicBlock,
     ) -> (Bx::BasicBlock, bool) {
         let span = self.terminator.source_info.span;
-        let lltarget = fx.blocks[target];
+        let lltarget = fx.llbb(target);
         let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
         match (self.funclet_bb, target_funclet) {
             (None, None) => (lltarget, false),
             (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => {
                 (lltarget, false)
             }
-            // jump *into* cleanup - need a landing pad if GNU
-            (None, Some(_)) => (fx.landing_pad_to(target), false),
+            // jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC
+            (None, Some(_)) => (fx.landing_pad_for(target), false),
             (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator),
-            (Some(_), Some(_)) => (fx.landing_pad_to(target), true),
+            (Some(_), Some(_)) => (fx.landing_pad_for(target), true),
         }
     }
 
@@ -112,13 +133,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         // If there is a cleanup block and the function we're calling can unwind, then
         // do an invoke, otherwise do a call.
         if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
-            let ret_bx = if let Some((_, target)) = destination {
-                fx.blocks[target]
+            let ret_llbb = if let Some((_, target)) = destination {
+                fx.llbb(target)
             } else {
                 fx.unreachable_block()
             };
             let invokeret =
-                bx.invoke(fn_ptr, &llargs, ret_bx, self.llblock(fx, cleanup), self.funclet(fx));
+                bx.invoke(fn_ptr, &llargs, ret_llbb, self.llblock(fx, cleanup), self.funclet(fx));
             bx.apply_attrs_callsite(&fn_abi, invokeret);
 
             if let Some((ret_dest, target)) = destination {
@@ -365,7 +386,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // Create the failure block and the conditional branch to it.
         let lltarget = helper.llblock(self, target);
-        let panic_block = self.new_block("panic");
+        let panic_block = bx.build_sibling_block("panic");
         if expected {
             bx.cond_br(cond, lltarget, panic_block.llbb());
         } else {
@@ -1170,38 +1191,88 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
     }
 
-    /// Returns the landing-pad wrapper around the given basic block.
-    ///
-    /// No-op in MSVC SEH scheme.
-    fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> Bx::BasicBlock {
-        if let Some(block) = self.landing_pads[target_bb] {
-            return block;
+    /// Returns the landing/cleanup pad wrapper around the given basic block.
+    // FIXME(eddyb) rename this to `eh_pad_for`.
+    fn landing_pad_for(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
+        if let Some(landing_pad) = self.landing_pads[bb] {
+            return landing_pad;
         }
 
-        let block = self.blocks[target_bb];
-        let landing_pad = self.landing_pad_uncached(block);
-        self.landing_pads[target_bb] = Some(landing_pad);
+        let landing_pad = self.landing_pad_for_uncached(bb);
+        self.landing_pads[bb] = Some(landing_pad);
         landing_pad
     }
 
-    fn landing_pad_uncached(&mut self, target_bb: Bx::BasicBlock) -> Bx::BasicBlock {
+    // FIXME(eddyb) rename this to `eh_pad_for_uncached`.
+    fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
+        let llbb = self.llbb(bb);
         if base::wants_msvc_seh(self.cx.sess()) {
-            span_bug!(self.mir.span, "landing pad was not inserted?")
-        }
-
-        let mut bx = self.new_block("cleanup");
+            let funclet;
+            let ret_llbb;
+            match self.mir[bb].terminator.as_ref().map(|t| &t.kind) {
+                // This is a basic block that we're aborting the program for,
+                // notably in an `extern` function. These basic blocks are inserted
+                // so that we assert that `extern` functions do indeed not panic,
+                // and if they do we abort the process.
+                //
+                // On MSVC these are tricky though (where we're doing funclets). If
+                // we were to do a cleanuppad (like below) the normal functions like
+                // `longjmp` would trigger the abort logic, terminating the
+                // program. Instead we insert the equivalent of `catch(...)` for C++
+                // which magically doesn't trigger when `longjmp` files over this
+                // frame.
+                //
+                // Lots more discussion can be found on #48251 but this codegen is
+                // modeled after clang's for:
+                //
+                //      try {
+                //          foo();
+                //      } catch (...) {
+                //          bar();
+                //      }
+                Some(&mir::TerminatorKind::Abort) => {
+                    let mut cs_bx = self.new_block(&format!("cs_funclet{:?}", bb));
+                    let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb));
+                    ret_llbb = cs_bx.llbb();
+
+                    let cs = cs_bx.catch_switch(None, None, 1);
+                    cs_bx.add_handler(cs, cp_bx.llbb());
+
+                    // The "null" here is actually a RTTI type descriptor for the
+                    // C++ personality function, but `catch (...)` has no type so
+                    // it's null. The 64 here is actually a bitfield which
+                    // represents that this is a catch-all block.
+                    let null = cp_bx.const_null(
+                        cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space),
+                    );
+                    let sixty_four = cp_bx.const_i32(64);
+                    funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
+                    cp_bx.br(llbb);
+                }
+                _ => {
+                    let mut cleanup_bx = self.new_block(&format!("funclet_{:?}", bb));
+                    ret_llbb = cleanup_bx.llbb();
+                    funclet = cleanup_bx.cleanup_pad(None, &[]);
+                    cleanup_bx.br(llbb);
+                }
+            }
+            self.funclets[bb] = Some(funclet);
+            ret_llbb
+        } else {
+            let mut bx = self.new_block("cleanup");
 
-        let llpersonality = self.cx.eh_personality();
-        let llretty = self.landing_pad_type();
-        let lp = bx.landing_pad(llretty, llpersonality, 1);
-        bx.set_cleanup(lp);
+            let llpersonality = self.cx.eh_personality();
+            let llretty = self.landing_pad_type();
+            let lp = bx.landing_pad(llretty, llpersonality, 1);
+            bx.set_cleanup(lp);
 
-        let slot = self.get_personality_slot(&mut bx);
-        slot.storage_live(&mut bx);
-        Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot);
+            let slot = self.get_personality_slot(&mut bx);
+            slot.storage_live(&mut bx);
+            Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot);
 
-        bx.br(target_bb);
-        bx.llbb()
+            bx.br(llbb);
+            bx.llbb()
+        }
     }
 
     fn landing_pad_type(&self) -> Bx::Type {
@@ -1218,14 +1289,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         })
     }
 
-    pub fn new_block(&self, name: &str) -> Bx {
-        Bx::new_block(self.cx, self.llfn, name)
+    // FIXME(eddyb) replace with `build_sibling_block`/`append_sibling_block`
+    // (which requires having a `Bx` already, and not all callers do).
+    fn new_block(&self, name: &str) -> Bx {
+        let llbb = Bx::append_block(self.cx, self.llfn, name);
+        Bx::build(self.cx, llbb)
+    }
+
+    /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already
+    /// cached in `self.cached_llbbs`, or created on demand (and cached).
+    // FIXME(eddyb) rename `llbb` and other `ll`-prefixed things to use a
+    // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbb`).
+    pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
+        self.cached_llbbs[bb].unwrap_or_else(|| {
+            // FIXME(eddyb) only name the block if `fewer_names` is `false`.
+            let llbb = Bx::append_block(self.cx, self.llfn, &format!("{:?}", bb));
+            self.cached_llbbs[bb] = Some(llbb);
+            llbb
+        })
     }
 
-    pub fn build_block(&self, bb: mir::BasicBlock) -> Bx {
-        let mut bx = Bx::with_cx(self.cx);
-        bx.position_at_end(self.blocks[bb]);
-        bx
+    pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx {
+        let llbb = self.llbb(bb);
+        Bx::build(self.cx, llbb)
     }
 
     fn make_return_dest(
diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
index 621ec0519c9..a283bf1de76 100644
--- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
@@ -31,7 +31,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         bx.add_coverage_counter(instance, id, code_region);
                     }
 
-                    let coverageinfo = bx.tcx().coverageinfo(instance.def_id());
+                    let coverageinfo = bx.tcx().coverageinfo(instance.def);
 
                     let fn_name = bx.get_pgo_func_name_var(instance);
                     let hash = bx.const_u64(function_source_hash);
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 91df67b53d2..3bbc481b610 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -1,4 +1,3 @@
-use crate::base;
 use crate::traits::*;
 use rustc_errors::ErrorReported;
 use rustc_middle::mir;
@@ -6,14 +5,12 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_target::abi::call::{FnAbi, PassMode};
-use rustc_target::abi::HasDataLayout;
 
 use std::iter;
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 
-use self::analyze::CleanupKind;
 use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
 use self::place::PlaceRef;
 use rustc_middle::mir::traversal;
@@ -43,18 +40,22 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     /// then later loaded when generating the DIVERGE_BLOCK.
     personality_slot: Option<PlaceRef<'tcx, Bx::Value>>,
 
-    /// A `Block` for each MIR `BasicBlock`
-    blocks: IndexVec<mir::BasicBlock, Bx::BasicBlock>,
+    /// A backend `BasicBlock` for each MIR `BasicBlock`, created lazily
+    /// as-needed (e.g. RPO reaching it or another block branching to it).
+    // FIXME(eddyb) rename `llbbs` and other `ll`-prefixed things to use a
+    // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbbs`).
+    cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
 
     /// The funclet status of each basic block
     cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
 
-    /// When targeting MSVC, this stores the cleanup info for each funclet
-    /// BB. This is initialized as we compute the funclets' head block in RPO.
+    /// When targeting MSVC, this stores the cleanup info for each funclet BB.
+    /// This is initialized at the same time as the `landing_pads` entry for the
+    /// funclets' head block, i.e. when needed by an unwind / `cleanup_ret` edge.
     funclets: IndexVec<mir::BasicBlock, Option<Bx::Funclet>>,
 
-    /// This stores the landing-pad block for a given BB, computed lazily on GNU
-    /// and eagerly on MSVC.
+    /// This stores the cached landing/cleanup pad block for a given BB.
+    // FIXME(eddyb) rename this to `eh_pads`.
     landing_pads: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
 
     /// Cached unreachable block
@@ -143,7 +144,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
 
-    let mut bx = Bx::new_block(cx, llfn, "start");
+    let start_llbb = Bx::append_block(cx, llfn, "start");
+    let mut bx = Bx::build(cx, start_llbb);
 
     if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) {
         bx.set_personality_fn(cx.eh_personality());
@@ -153,19 +155,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // Allocate a `Block` for every basic block, except
     // the start block, if nothing loops back to it.
     let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
-    let block_bxs: IndexVec<mir::BasicBlock, Bx::BasicBlock> = mir
-        .basic_blocks()
-        .indices()
-        .map(|bb| {
-            if bb == mir::START_BLOCK && !reentrant_start_block {
-                bx.llbb()
-            } else {
-                bx.build_sibling_block(&format!("{:?}", bb)).llbb()
-            }
-        })
-        .collect();
+    let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> =
+        mir.basic_blocks()
+            .indices()
+            .map(|bb| {
+                if bb == mir::START_BLOCK && !reentrant_start_block {
+                    Some(start_llbb)
+                } else {
+                    None
+                }
+            })
+            .collect();
 
-    let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs);
     let mut fx = FunctionCx {
         instance,
         mir,
@@ -173,11 +174,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         fn_abi,
         cx,
         personality_slot: None,
-        blocks: block_bxs,
+        cached_llbbs,
         unreachable_block: None,
         cleanup_kinds,
-        landing_pads,
-        funclets,
+        landing_pads: IndexVec::from_elem(None, mir.basic_blocks()),
+        funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks().len()),
         locals: IndexVec::new(),
         debug_context,
         per_local_var_debug_info: None,
@@ -248,100 +249,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     // Branch to the START block, if it's not the entry block.
     if reentrant_start_block {
-        bx.br(fx.blocks[mir::START_BLOCK]);
+        bx.br(fx.llbb(mir::START_BLOCK));
     }
 
-    let rpo = traversal::reverse_postorder(&mir);
-    let mut visited = BitSet::new_empty(mir.basic_blocks().len());
-
     // Codegen the body of each block using reverse postorder
-    for (bb, _) in rpo {
-        visited.insert(bb.index());
+    // FIXME(eddyb) reuse RPO iterator between `analysis` and this.
+    for (bb, _) in traversal::reverse_postorder(&mir) {
         fx.codegen_block(bb);
     }
-
-    // Remove blocks that haven't been visited, or have no
-    // predecessors.
-    for bb in mir.basic_blocks().indices() {
-        // Unreachable block
-        if !visited.contains(bb.index()) {
-            debug!("codegen_mir: block {:?} was not visited", bb);
-            unsafe {
-                bx.delete_basic_block(fx.blocks[bb]);
-            }
-        }
-    }
-}
-
-fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
-    mir: &'tcx mir::Body<'tcx>,
-    bx: &mut Bx,
-    cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
-    block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>,
-) -> (
-    IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
-    IndexVec<mir::BasicBlock, Option<Bx::Funclet>>,
-) {
-    iter::zip(block_bxs.iter_enumerated(), cleanup_kinds)
-        .map(|((bb, &llbb), cleanup_kind)| {
-            match *cleanup_kind {
-                CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {}
-                _ => return (None, None),
-            }
-
-            let funclet;
-            let ret_llbb;
-            match mir[bb].terminator.as_ref().map(|t| &t.kind) {
-                // This is a basic block that we're aborting the program for,
-                // notably in an `extern` function. These basic blocks are inserted
-                // so that we assert that `extern` functions do indeed not panic,
-                // and if they do we abort the process.
-                //
-                // On MSVC these are tricky though (where we're doing funclets). If
-                // we were to do a cleanuppad (like below) the normal functions like
-                // `longjmp` would trigger the abort logic, terminating the
-                // program. Instead we insert the equivalent of `catch(...)` for C++
-                // which magically doesn't trigger when `longjmp` files over this
-                // frame.
-                //
-                // Lots more discussion can be found on #48251 but this codegen is
-                // modeled after clang's for:
-                //
-                //      try {
-                //          foo();
-                //      } catch (...) {
-                //          bar();
-                //      }
-                Some(&mir::TerminatorKind::Abort) => {
-                    let mut cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb));
-                    let mut cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb));
-                    ret_llbb = cs_bx.llbb();
-
-                    let cs = cs_bx.catch_switch(None, None, 1);
-                    cs_bx.add_handler(cs, cp_bx.llbb());
-
-                    // The "null" here is actually a RTTI type descriptor for the
-                    // C++ personality function, but `catch (...)` has no type so
-                    // it's null. The 64 here is actually a bitfield which
-                    // represents that this is a catch-all block.
-                    let null = bx.const_null(
-                        bx.type_i8p_ext(bx.cx().data_layout().instruction_address_space),
-                    );
-                    let sixty_four = bx.const_i32(64);
-                    funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
-                    cp_bx.br(llbb);
-                }
-                _ => {
-                    let mut cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
-                    ret_llbb = cleanup_bx.llbb();
-                    funclet = cleanup_bx.cleanup_pad(None, &[]);
-                    cleanup_bx.br(llbb);
-                }
-            };
-
-            (Some(ret_llbb), Some(funclet))
-        })
-        .unzip()
 }
 
 /// Produces, for each argument, a `Value` pointing at the
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 1bc05f30e5c..29b2db5d4d7 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -40,14 +40,21 @@ pub trait BuilderMethods<'a, 'tcx>:
     + HasParamEnv<'tcx>
     + HasTargetSpec
 {
-    fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self;
-    fn with_cx(cx: &'a Self::CodegenCx) -> Self;
-    fn build_sibling_block(&self, name: &str) -> Self;
+    fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self;
+
     fn cx(&self) -> &Self::CodegenCx;
     fn llbb(&self) -> Self::BasicBlock;
+
     fn set_span(&mut self, span: Span);
 
-    fn position_at_end(&mut self, llbb: Self::BasicBlock);
+    // FIXME(eddyb) replace uses of this with `append_sibling_block`.
+    fn append_block(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &str) -> Self::BasicBlock;
+
+    fn append_sibling_block(&mut self, name: &str) -> Self::BasicBlock;
+
+    // FIXME(eddyb) replace with callers using `append_sibling_block`.
+    fn build_sibling_block(&mut self, name: &str) -> Self;
+
     fn ret_void(&mut self);
     fn ret(&mut self, v: Self::Value);
     fn br(&mut self, dest: Self::BasicBlock);
@@ -291,6 +298,5 @@ pub trait BuilderMethods<'a, 'tcx>:
     ) -> Self::Value;
     fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
 
-    unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock);
     fn do_not_inline(&mut self, llret: Self::Value);
 }
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 18114634209..c9b36dd0c24 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -21,7 +21,6 @@ use rustc_data_structures::sync::SeqCst;
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_feature::find_gated_cfg;
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
@@ -389,7 +388,7 @@ fn run_compiler(
             }
 
             queries.global_ctxt()?.peek_mut().enter(|tcx| {
-                let result = tcx.analysis(LOCAL_CRATE);
+                let result = tcx.analysis(());
                 if sess.opts.debugging_opts.save_analysis {
                     let crate_name = queries.crate_name()?.peek().clone();
                     sess.time("save_analysis", || {
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index e0c140b143b..370ec053cbb 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -4,7 +4,6 @@ use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir_pretty as pprust_hir;
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::{self, TyCtxt};
@@ -74,7 +73,7 @@ where
             f(&annotation, tcx.hir().krate())
         }
         PpHirMode::Typed => {
-            abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
+            abort_on_err(tcx.analysis(()), tcx.sess);
 
             let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) };
             tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate()))
@@ -475,7 +474,7 @@ fn print_with_analysis(
     ppm: PpMode,
     ofile: Option<&Path>,
 ) -> Result<(), ErrorReported> {
-    tcx.analysis(LOCAL_CRATE)?;
+    tcx.analysis(())?;
 
     let out = match ppm {
         Mir => {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0277.md b/compiler/rustc_error_codes/src/error_codes/E0277.md
index 9f6db6ed7a2..5f05b59d5a6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0277.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0277.md
@@ -29,16 +29,16 @@ trait Foo {
     fn bar(&self);
 }
 
-fn some_func<T: Foo>(foo: T) {
-    foo.bar(); // we can now use this method since i32 implements the
-               // Foo trait
-}
-
 // we implement the trait on the i32 type
 impl Foo for i32 {
     fn bar(&self) {}
 }
 
+fn some_func<T: Foo>(foo: T) {
+    foo.bar(); // we can now use this method since i32 implements the
+               // Foo trait
+}
+
 fn main() {
     some_func(5i32); // ok!
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index f53ce7ceace..65352f0bc6e 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -5,7 +5,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(backtrace)]
-#![feature(extended_key_value_attributes)]
+#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(nll)]
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e8642a52749..eef71e096a5 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -281,6 +281,8 @@ declare_features! (
     (accepted, or_patterns, "1.53.0", Some(54883), None),
     /// Allows defining identifiers beyond ASCII.
     (accepted, non_ascii_idents, "1.53.0", Some(55467), None),
+    /// Allows arbitrary expressions in key-value attributes at parse time.
+    (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 535cb132766..2cef46a844a 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -601,9 +601,6 @@ declare_features! (
     /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
     (active, capture_disjoint_fields, "1.49.0", Some(53488), None),
 
-    /// Allows arbitrary expressions in key-value attributes at parse time.
-    (active, extended_key_value_attributes, "1.50.0", Some(78835), None),
-
     /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
     (active, const_generics_defaults, "1.51.0", Some(44580), None),
 
@@ -650,6 +647,9 @@ declare_features! (
     /// Allows unsizing coercions in `const fn`.
     (active, const_fn_unsize, "1.53.0", Some(64992), None),
 
+    /// Allows `async {}` expressions in const contexts.
+    (active, const_async_blocks, "1.53.0", Some(85368), None),
+
     /// Allows using imported `main` function
     (active, imported_main, "1.53.0", Some(28937), None),
 
@@ -668,6 +668,9 @@ declare_features! (
     /// Allows specifying the as-needed link modifier
     (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
 
+    /// Allows unnamed fields of struct and union type
+    (active, unnamed_fields, "1.53.0", Some(49804), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -692,7 +695,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::repr128,
     sym::unsized_locals,
     sym::capture_disjoint_fields,
-    sym::const_generics_defaults,
     sym::inherent_associated_types,
     sym::type_alias_impl_trait,
     sym::native_link_modifiers,
@@ -700,6 +702,8 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::native_link_modifiers_verbatim,
     sym::native_link_modifiers_whole_archive,
     sym::native_link_modifiers_as_needed,
+    sym::rustc_insignificant_dtor,
+    sym::unnamed_fields,
 ];
 
 /// Some features are not allowed to be used together at the same time, if
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 51d69167f7b..e7e128f8a9b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -556,6 +556,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_variance, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
     rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 7b788b13b9f..0b8535f8ca5 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -308,12 +308,12 @@ language_item_table! {
 
     Termination,             sym::termination,         termination,                Target::Trait;
 
-    Try,                     kw::Try,                  try_trait,                  Target::Trait;
+    Try,                     sym::Try,                 try_trait,                  Target::Trait;
 
     // Language items from AST lowering
-    TryFromError,            sym::from_error,          from_error_fn,              Target::Method(MethodKind::Trait { body: false });
-    TryFromOk,               sym::from_ok,             from_ok_fn,                 Target::Method(MethodKind::Trait { body: false });
-    TryIntoResult,           sym::into_result,         into_result_fn,             Target::Method(MethodKind::Trait { body: false });
+    TryTraitFromResidual,    sym::from_residual,       from_residual_fn,           Target::Method(MethodKind::Trait { body: false });
+    TryTraitFromOutput,      sym::from_output,         from_output_fn,             Target::Method(MethodKind::Trait { body: false });
+    TryTraitBranch,          sym::branch,              branch_fn,                  Target::Method(MethodKind::Trait { body: false });
 
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant;
     PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant;
@@ -331,6 +331,9 @@ language_item_table! {
     ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant;
     ResultErr,               sym::Err,                 result_err_variant,         Target::Variant;
 
+    ControlFlowContinue,     sym::Continue,            cf_continue_variant,        Target::Variant;
+    ControlFlowBreak,        sym::Break,               cf_break_variant,           Target::Variant;
+
     IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false });
     IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false});
 
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 65c99535c4e..71e997994de 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,7 +4,7 @@
 
 #![feature(crate_visibility_modifier)]
 #![feature(const_panic)]
-#![feature(extended_key_value_attributes)]
+#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(in_band_lifetimes)]
 #![feature(once_cell)]
 #![cfg_attr(bootstrap, feature(or_patterns))]
diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs
index 5fb2c1cb9c9..8220eb6c657 100644
--- a/compiler/rustc_incremental/src/assert_module_sources.rs
+++ b/compiler/rustc_incremental/src/assert_module_sources.rs
@@ -36,7 +36,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
         }
 
         let available_cgus = tcx
-            .collect_and_partition_mono_items(LOCAL_CRATE)
+            .collect_and_partition_mono_items(())
             .1
             .iter()
             .map(|cgu| cgu.name().to_string())
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 9ffcddfae99..49359130162 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -3,7 +3,6 @@
 use self::CombineMapType::*;
 use self::UndoLog::*;
 
-use super::unify_key;
 use super::{
     InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
 };
@@ -12,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_data_structures::unify as ut;
-use rustc_data_structures::unify::UnifyKey;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
+use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
 use rustc_middle::ty::ReStatic;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{ReLateBound, ReVar};
@@ -54,7 +53,7 @@ pub struct RegionConstraintStorage<'tcx> {
     /// code is iterating to a fixed point, because otherwise we sometimes
     /// would wind up with a fresh stream of region variables that have been
     /// equated but appear distinct.
-    pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>,
+    pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>,
 
     /// a flag set to true when we perform any unifications; this is used
     /// to micro-optimize `take_and_reset_data`
@@ -407,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         // `RegionConstraintData` contains the relationship here.
         if *any_unifications {
             *any_unifications = false;
-            self.unification_table()
-                .reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
+            self.unification_table().reset_unifications(|_| UnifiedRegion(None));
         }
 
         data
@@ -435,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ) -> RegionVid {
         let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
 
-        let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid });
-        assert_eq!(vid, u_vid);
+        let u_vid = self.unification_table().new_key(UnifiedRegion(None));
+        assert_eq!(vid, u_vid.vid);
         self.undo_log.push(AddVar(vid));
         debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
         vid
@@ -498,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
             self.make_subregion(origin.clone(), sub, sup);
             self.make_subregion(origin, sup, sub);
 
-            if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
-                debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
-                self.unification_table().union(sub, sup);
-                self.any_unifications = true;
+            match (sub, sup) {
+                (&ty::ReVar(sub), &ty::ReVar(sup)) => {
+                    debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
+                    self.unification_table().union(sub, sup);
+                    self.any_unifications = true;
+                }
+                (&ty::ReVar(vid), value) | (value, &ty::ReVar(vid)) => {
+                    debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
+                    self.unification_table().union_value(vid, UnifiedRegion(Some(value)));
+                    self.any_unifications = true;
+                }
+                (_, _) => {}
             }
         }
     }
@@ -617,8 +623,29 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid {
-        self.unification_table().probe_value(rid).min_vid
+    /// Resolves the passed RegionVid to the root RegionVid in the unification table
+    pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
+        self.unification_table().find(rid).vid
+    }
+
+    /// If the Region is a `ReVar`, then resolves it either to the root value in
+    /// the unification table, if it exists, or to the root `ReVar` in the table.
+    /// If the Region is not a `ReVar`, just returns the Region itself.
+    pub fn opportunistic_resolve_region(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        region: ty::Region<'tcx>,
+    ) -> ty::Region<'tcx> {
+        match region {
+            ty::ReVar(rid) => {
+                let unified_region = self.unification_table().probe_value(*rid);
+                unified_region.0.unwrap_or_else(|| {
+                    let root = self.unification_table().find(*rid).vid;
+                    tcx.reuse_or_mk_region(region, ty::ReVar(root))
+                })
+            }
+            _ => region,
+        }
     }
 
     fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
@@ -673,8 +700,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         &self,
         value_count: usize,
     ) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
-        let range = RegionVid::from_index(value_count as u32)
-            ..RegionVid::from_index(self.unification_table.len() as u32);
+        let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len());
         (
             range.clone(),
             (range.start.index()..range.end.index())
@@ -696,7 +722,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     #[inline]
-    fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> {
+    fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
         ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index f41e872e004..5ad2519a93c 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -3,6 +3,7 @@ use std::marker::PhantomData;
 use rustc_data_structures::snapshot_vec as sv;
 use rustc_data_structures::undo_log::{Rollback, UndoLogs};
 use rustc_data_structures::unify as ut;
+use rustc_middle::infer::unify_key::RegionVidKey;
 use rustc_middle::ty;
 
 use crate::{
@@ -22,7 +23,7 @@ pub(crate) enum UndoLog<'tcx> {
     IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
     FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
     RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
-    RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
+    RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
     ProjectionCache(traits::UndoLog<'tcx>),
     PushRegionObligation,
 }
@@ -55,7 +56,7 @@ impl_from! {
 
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
 
-    RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
+    RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
     ProjectionCache(traits::UndoLog<'tcx>),
 }
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 06bec91501f..e2220e3b60d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::Crate;
 use rustc_lint::LintStore;
 use rustc_metadata::creader::CStore;
@@ -805,9 +805,7 @@ pub fn create_global_ctxt<'tcx>(
 
 /// Runs the resolution, type-checking, region checking and other
 /// miscellaneous analysis passes on the crate.
-fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
-    assert_eq!(cnum, LOCAL_CRATE);
-
+fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
     rustc_passes::hir_id_validator::check_crate(tcx);
 
     let sess = tcx.sess;
@@ -816,14 +814,13 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
     sess.time("misc_checking_1", || {
         parallel!(
             {
-                entry_point = sess
-                    .time("looking_for_entry_point", || rustc_passes::entry::find_entry_point(tcx));
+                entry_point = sess.time("looking_for_entry_point", || tcx.entry_fn(()));
 
-                sess.time("looking_for_plugin_registrar", || {
-                    plugin::build::find_plugin_registrar(tcx)
-                });
+                sess.time("looking_for_plugin_registrar", || tcx.ensure().plugin_registrar_fn(()));
 
-                sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
+                sess.time("looking_for_derive_registrar", || {
+                    tcx.ensure().proc_macro_decls_static(())
+                });
 
                 let cstore = tcx
                     .cstore_as_any()
@@ -903,11 +900,11 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
     sess.time("misc_checking_3", || {
         parallel!(
             {
-                tcx.ensure().privacy_access_levels(LOCAL_CRATE);
+                tcx.ensure().privacy_access_levels(());
 
                 parallel!(
                     {
-                        tcx.ensure().check_private_in_public(LOCAL_CRATE);
+                        tcx.ensure().check_private_in_public(());
                     },
                     {
                         sess.time("death_checking", || rustc_passes::dead::check_crate(tcx));
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 4637055a82d..88cf6275ebb 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -1,21 +1,15 @@
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
-pub fn find(tcx: TyCtxt<'_>) -> Option<DefId> {
-    tcx.proc_macro_decls_static(LOCAL_CRATE)
-}
-
-fn proc_macro_decls_static(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
-    assert_eq!(cnum, LOCAL_CRATE);
-
+fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut finder = Finder { tcx, decls: None };
     tcx.hir().krate().visit_all_item_likes(&mut finder);
 
-    finder.decls.map(|id| tcx.hir().local_def_id(id).to_def_id())
+    finder.decls.map(|id| tcx.hir().local_def_id(id))
 }
 
 struct Finder<'tcx> {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index bc94fb67ac3..92d05e48068 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -285,7 +285,7 @@ impl<'tcx> Queries<'tcx> {
         self.ongoing_codegen.compute(|| {
             let outputs = self.prepare_outputs()?;
             self.global_ctxt()?.peek_mut().enter(|tcx| {
-                tcx.analysis(LOCAL_CRATE).ok();
+                tcx.analysis(()).ok();
 
                 // Don't do code generation if there were any errors
                 self.session().compile_status()?;
@@ -302,7 +302,7 @@ impl<'tcx> Queries<'tcx> {
     /// to write UI tests that actually test that compilation succeeds without reporting
     /// an error.
     fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
-        let def_id = match tcx.entry_fn(LOCAL_CRATE) {
+        let def_id = match tcx.entry_fn(()) {
             Some((def_id, _)) => def_id,
             _ => return,
         };
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index fd29053433e..7b1660b501b 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -922,7 +922,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
     }
 }
 
-/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)"
+/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
 pub fn version_str() -> Option<&'static str> {
     option_env!("CFG_VERSION")
 }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index d325b5fe7f8..e504662bb5e 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -18,7 +18,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
 use rustc_ast as ast;
 use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
 use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::map::Map;
@@ -375,7 +375,7 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
     module_def_id: LocalDefId,
     pass: T,
 ) {
-    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
+    let access_levels = &tcx.privacy_access_levels(());
 
     let context = LateContext {
         tcx,
@@ -423,7 +423,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
 }
 
 fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
-    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
+    let access_levels = &tcx.privacy_access_levels(());
 
     let krate = tcx.hir().krate();
 
@@ -448,6 +448,10 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
         lint_callback!(cx, check_crate, krate);
 
         hir_visit::walk_crate(cx, krate);
+        for attr in krate.non_exported_macro_attrs {
+            // This HIR ID is a lie, since the macro ID isn't available.
+            cx.visit_attribute(hir::CRATE_HIR_ID, attr);
+        }
 
         lint_callback!(cx, check_crate_post, krate);
     })
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 54909381a10..91cdef9b089 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -6,8 +6,7 @@ use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::{intravisit, HirId};
+use rustc_hir::{intravisit, HirId, CRATE_HIR_ID};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::LevelAndSource;
 use rustc_middle::lint::LintDiagnosticBuilder;
@@ -28,10 +27,9 @@ use tracing::debug;
 
 use std::cmp;
 
-fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
-    assert_eq!(cnum, LOCAL_CRATE);
+fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
     let store = unerased_lint_store(tcx);
-    let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX });
+    let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
     let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs);
     let mut builder = LintLevelMapBuilder { levels, tcx, store };
     let krate = tcx.hir().krate();
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index de5279c4a8d..b27eef376c4 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -406,17 +406,17 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> {
+        let ctxt = SyntaxContext::decode(decoder)?;
         let tag = u8::decode(decoder)?;
 
-        if tag == TAG_INVALID_SPAN {
-            return Ok(DUMMY_SP);
+        if tag == TAG_PARTIAL_SPAN {
+            return Ok(DUMMY_SP.with_ctxt(ctxt));
         }
 
         debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
 
         let lo = BytePos::decode(decoder)?;
         let len = BytePos::decode(decoder)?;
-        let ctxt = SyntaxContext::decode(decoder)?;
         let hi = lo + len;
 
         let sess = if let Some(sess) = decoder.sess {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 82ca634f282..e25b22c8331 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -185,19 +185,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     }
     native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
     foreign_modules => { cdata.get_foreign_modules(tcx) }
-    plugin_registrar_fn => {
-        cdata.root.plugin_registrar_fn.map(|index| {
-            DefId { krate: def_id.krate, index }
-        })
-    }
-    proc_macro_decls_static => {
-        cdata.root.proc_macro_data.as_ref().map(|data| {
-            DefId {
-                krate: def_id.krate,
-                index: data.proc_macro_decls_static,
-            }
-        })
-    }
     crate_disambiguator => { cdata.root.disambiguator }
     crate_hash => { cdata.root.hash }
     crate_host_hash => { cdata.host_hash }
@@ -296,11 +283,10 @@ pub fn provide(providers: &mut Providers) {
         // external item that is visible from at least one local module) to a
         // sufficiently visible parent (considering modules that re-export the
         // external item to be parents).
-        visible_parent_map: |tcx, cnum| {
+        visible_parent_map: |tcx, ()| {
             use std::collections::hash_map::Entry;
             use std::collections::vec_deque::VecDeque;
 
-            assert_eq!(cnum, LOCAL_CRATE);
             let mut visible_parent_map: DefIdMap<DefId> = Default::default();
 
             // Issue 46112: We want the map to prefer the shortest
@@ -348,7 +334,7 @@ pub fn provide(providers: &mut Providers) {
                                 Entry::Occupied(mut entry) => {
                                     // If `child` is defined in crate `cnum`, ensure
                                     // that it is mapped to a parent in `cnum`.
-                                    if child.krate == cnum && entry.get().krate != cnum {
+                                    if child.is_local() && entry.get().is_local() {
                                         entry.insert(parent);
                                     }
                                 }
@@ -370,17 +356,14 @@ pub fn provide(providers: &mut Providers) {
             visible_parent_map
         },
 
-        dependency_formats: |tcx, cnum| {
-            assert_eq!(cnum, LOCAL_CRATE);
-            Lrc::new(crate::dependency_format::calculate(tcx))
-        },
+        dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)),
         has_global_allocator: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
             CStore::from_tcx(tcx).has_global_allocator()
         },
-        postorder_cnums: |tcx, cnum| {
-            assert_eq!(cnum, LOCAL_CRATE);
-            tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(cnum))
+        postorder_cnums: |tcx, ()| {
+            tcx.arena
+                .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
         },
 
         ..*providers
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 19c713665c7..0c31430598a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -187,11 +187,48 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        if *self == rustc_span::DUMMY_SP {
-            return TAG_INVALID_SPAN.encode(s);
+        let span = self.data();
+
+        // Don't serialize any `SyntaxContext`s from a proc-macro crate,
+        // since we don't load proc-macro dependencies during serialization.
+        // This means that any hygiene information from macros used *within*
+        // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
+        // definition) will be lost.
+        //
+        // This can show up in two ways:
+        //
+        // 1. Any hygiene information associated with identifier of
+        // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
+        // Since proc-macros can only be invoked from a different crate,
+        // real code should never need to care about this.
+        //
+        // 2. Using `Span::def_site` or `Span::mixed_site` will not
+        // include any hygiene information associated with the definition
+        // site. This means that a proc-macro cannot emit a `$crate`
+        // identifier which resolves to one of its dependencies,
+        // which also should never come up in practice.
+        //
+        // Additionally, this affects `Span::parent`, and any other
+        // span inspection APIs that would otherwise allow traversing
+        // the `SyntaxContexts` associated with a span.
+        //
+        // None of these user-visible effects should result in any
+        // cross-crate inconsistencies (getting one behavior in the same
+        // crate, and a different behavior in another crate) due to the
+        // limited surface that proc-macros can expose.
+        //
+        // IMPORTANT: If this is ever changed, be sure to update
+        // `rustc_span::hygiene::raw_encode_expn_id` to handle
+        // encoding `ExpnData` for proc-macro crates.
+        if s.is_proc_macro {
+            SyntaxContext::root().encode(s)?;
+        } else {
+            span.ctxt.encode(s)?;
         }
 
-        let span = self.data();
+        if self.is_dummy() {
+            return TAG_PARTIAL_SPAN.encode(s);
+        }
 
         // The Span infrastructure should make sure that this invariant holds:
         debug_assert!(span.lo <= span.hi);
@@ -206,7 +243,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         if !s.source_file_cache.0.contains(span.hi) {
             // Unfortunately, macro expansion still sometimes generates Spans
             // that malformed in this way.
-            return TAG_INVALID_SPAN.encode(s);
+            return TAG_PARTIAL_SPAN.encode(s);
         }
 
         let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!");
@@ -262,43 +299,6 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         let len = hi - lo;
         len.encode(s)?;
 
-        // Don't serialize any `SyntaxContext`s from a proc-macro crate,
-        // since we don't load proc-macro dependencies during serialization.
-        // This means that any hygiene information from macros used *within*
-        // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
-        // definition) will be lost.
-        //
-        // This can show up in two ways:
-        //
-        // 1. Any hygiene information associated with identifier of
-        // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
-        // Since proc-macros can only be invoked from a different crate,
-        // real code should never need to care about this.
-        //
-        // 2. Using `Span::def_site` or `Span::mixed_site` will not
-        // include any hygiene information associated with the definition
-        // site. This means that a proc-macro cannot emit a `$crate`
-        // identifier which resolves to one of its dependencies,
-        // which also should never come up in practice.
-        //
-        // Additionally, this affects `Span::parent`, and any other
-        // span inspection APIs that would otherwise allow traversing
-        // the `SyntaxContexts` associated with a span.
-        //
-        // None of these user-visible effects should result in any
-        // cross-crate inconsistencies (getting one behavior in the same
-        // crate, and a different behavior in another crate) due to the
-        // limited surface that proc-macros can expose.
-        //
-        // IMPORTANT: If this is ever changed, be sure to update
-        // `rustc_span::hygiene::raw_encode_expn_id` to handle
-        // encoding `ExpnData` for proc-macro crates.
-        if s.is_proc_macro {
-            SyntaxContext::root().encode(s)?;
-        } else {
-            span.ctxt.encode(s)?;
-        }
-
         if tag == TAG_VALID_SPAN_FOREIGN {
             // This needs to be two lines to avoid holding the `s.source_file_cache`
             // while calling `cnum.encode(s)`
@@ -678,7 +678,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
             has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
             has_default_lib_allocator,
-            plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
             proc_macro_data,
             compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
             needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
@@ -970,13 +969,12 @@ impl EncodeContext<'a, 'tcx> {
                 record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
             }
         }
-        let inherent_impls = tcx.crate_inherent_impls(LOCAL_CRATE);
+        let inherent_impls = tcx.crate_inherent_impls(());
         for (def_id, implementations) in inherent_impls.inherent_impls.iter() {
-            assert!(def_id.is_local());
             if implementations.is_empty() {
                 continue;
             }
-            record!(self.tables.inherent_impls[def_id] <- implementations.iter().map(|&def_id| {
+            record!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
                 assert!(def_id.is_local());
                 def_id.index
             }));
@@ -1263,7 +1261,7 @@ impl EncodeContext<'a, 'tcx> {
 
         let mut keys_and_jobs = self
             .tcx
-            .mir_keys(LOCAL_CRATE)
+            .mir_keys(())
             .iter()
             .filter_map(|&def_id| {
                 let (encode_const, encode_opt) = should_encode_mir(self.tcx, def_id);
@@ -1601,7 +1599,7 @@ impl EncodeContext<'a, 'tcx> {
             let tcx = self.tcx;
             let hir = tcx.hir();
 
-            let proc_macro_decls_static = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap().index;
+            let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
             let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied();
             let macros = self.lazy(hir.krate().proc_macros.iter().map(|p| p.owner.local_def_index));
             let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
@@ -1798,7 +1796,7 @@ impl EncodeContext<'a, 'tcx> {
 
     fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
         empty_proc_macro!(self);
-        let formats = self.tcx.dependency_formats(LOCAL_CRATE);
+        let formats = self.tcx.dependency_formats(());
         for (ty, arr) in formats.iter() {
             if *ty != CrateType::Dylib {
                 continue;
@@ -2028,7 +2026,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
         return;
     }
 
-    par_iter(tcx.mir_keys(LOCAL_CRATE)).for_each(|&def_id| {
+    par_iter(tcx.mir_keys(())).for_each(|&def_id| {
         let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
 
         if encode_const {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 6b375045f14..04fe5cf5890 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -209,7 +209,6 @@ crate struct CrateRoot<'tcx> {
     has_global_allocator: bool,
     has_panic_handler: bool,
     has_default_lib_allocator: bool,
-    plugin_registrar_fn: Option<DefIndex>,
 
     crate_deps: Lazy<[CrateDep]>,
     dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
@@ -451,4 +450,4 @@ struct GeneratorData<'tcx> {
 // Tags used for encoding Spans:
 const TAG_VALID_SPAN_LOCAL: u8 = 0;
 const TAG_VALID_SPAN_FOREIGN: u8 = 1;
-const TAG_INVALID_SPAN: u8 = 2;
+const TAG_PARTIAL_SPAN: u8 = 2;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 09736c6f1e5..d154b7804f0 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -150,7 +150,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
 
 impl<'hir> Map<'hir> {
     pub fn krate(&self) -> &'hir Crate<'hir> {
-        self.tcx.hir_crate(LOCAL_CRATE)
+        self.tcx.hir_crate(())
     }
 
     #[inline]
@@ -489,7 +489,7 @@ impl<'hir> Map<'hir> {
     }
 
     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[..])
+        self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
     /// Gets the attributes on the crate. This is preferable to
@@ -928,9 +928,7 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 }
 
-pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> {
-    assert_eq!(cnum, LOCAL_CRATE);
-
+pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> {
     let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
 
     let hcx = tcx.create_stable_hashing_context();
@@ -943,10 +941,12 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe
 }
 
 pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
+    assert_eq!(crate_num, LOCAL_CRATE);
+
     let mut hcx = tcx.create_stable_hashing_context();
 
     let mut hir_body_nodes: Vec<_> = tcx
-        .index_hir(crate_num)
+        .index_hir(())
         .map
         .iter_enumerated()
         .filter_map(|(def_id, hod)| {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 565664778e5..879372c65ea 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -13,7 +13,7 @@ use rustc_ast::Attribute;
 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::{LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 use rustc_span::DUMMY_SP;
@@ -123,14 +123,14 @@ pub fn provide(providers: &mut Providers) {
         let hir = tcx.hir();
         hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
     };
-    providers.hir_crate = |tcx, _| tcx.untracked_crate;
+    providers.hir_crate = |tcx, ()| tcx.untracked_crate;
     providers.index_hir = map::index_hir;
     providers.crate_hash = map::crate_hash;
     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.hir_owner = |tcx, id| tcx.index_hir(()).map[id].signature;
+    providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].with_bodies.as_deref();
     providers.hir_owner_parent = |tcx, id| {
-        let index = tcx.index_hir(LOCAL_CRATE);
+        let index = tcx.index_hir(());
         index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
     };
     providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
@@ -151,4 +151,5 @@ pub fn provide(providers: &mut Providers) {
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
+    providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
 }
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 641cf23781e..0b05dd5c0ba 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -16,37 +16,48 @@ pub trait ToType {
 }
 
 #[derive(PartialEq, Copy, Clone, Debug)]
-pub struct RegionVidKey {
-    /// The minimum region vid in the unification set. This is needed
-    /// to have a canonical name for a type to prevent infinite
-    /// recursion.
-    pub min_vid: ty::RegionVid,
-}
-
-impl UnifyValue for RegionVidKey {
-    type Error = NoError;
+pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
 
-    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
-        let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
-            value1.min_vid
-        } else {
-            value2.min_vid
-        };
+#[derive(PartialEq, Copy, Clone, Debug)]
+pub struct RegionVidKey<'tcx> {
+    pub vid: ty::RegionVid,
+    pub phantom: PhantomData<UnifiedRegion<'tcx>>,
+}
 
-        Ok(RegionVidKey { min_vid })
+impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
+    fn from(vid: ty::RegionVid) -> Self {
+        RegionVidKey { vid, phantom: PhantomData }
     }
 }
 
-impl UnifyKey for ty::RegionVid {
-    type Value = RegionVidKey;
+impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
+    type Value = UnifiedRegion<'tcx>;
     fn index(&self) -> u32 {
-        u32::from(*self)
+        self.vid.as_u32()
     }
-    fn from_index(i: u32) -> ty::RegionVid {
-        ty::RegionVid::from(i)
+    fn from_index(i: u32) -> Self {
+        RegionVidKey::from(ty::RegionVid::from_u32(i))
     }
     fn tag() -> &'static str {
-        "RegionVid"
+        "RegionVidKey"
+    }
+}
+
+impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
+    type Error = NoError;
+
+    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
+        Ok(match (value1.0, value2.0) {
+            // Here we can just pick one value, because the full constraints graph
+            // will be handled later. Ideally, we might want a `MultipleValues`
+            // variant or something. For now though, this is fine.
+            (Some(_), Some(_)) => *value1,
+
+            (Some(_), _) => *value1,
+            (_, Some(_)) => *value2,
+
+            (None, None) => *value1,
+        })
     }
 }
 
diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs
index 82b9ebcc7ec..d63116e29c8 100644
--- a/compiler/rustc_middle/src/middle/cstore.rs
+++ b/compiler/rustc_middle/src/middle/cstore.rs
@@ -251,7 +251,7 @@ pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum,
             Some((cnum, path))
         })
         .collect::<Vec<_>>();
-    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned();
+    let mut ordering = tcx.postorder_cnums(()).to_owned();
     ordering.reverse();
     libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a));
     libs
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 766d6a06f7e..929818bd1ee 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -27,8 +27,6 @@ pub struct Allocation<Tag = (), Extra = ()> {
     relocations: Relocations<Tag>,
     /// Denotes which part of this allocation is initialized.
     init_mask: InitMask,
-    /// The size of the allocation. Currently, must always equal `bytes.len()`.
-    pub size: Size,
     /// The alignment of the allocation to detect unaligned reads.
     /// (`Align` guarantees that this is a power of two.)
     pub align: Align,
@@ -94,7 +92,6 @@ impl<Tag> Allocation<Tag> {
             bytes,
             relocations: Relocations::new(),
             init_mask: InitMask::new(size, true),
-            size,
             align,
             mutability: Mutability::Not,
             extra: (),
@@ -110,7 +107,6 @@ impl<Tag> Allocation<Tag> {
             bytes: vec![0; size.bytes_usize()],
             relocations: Relocations::new(),
             init_mask: InitMask::new(size, false),
-            size,
             align,
             mutability: Mutability::Mut,
             extra: (),
@@ -127,7 +123,6 @@ impl Allocation<(), ()> {
     ) -> Allocation<T, E> {
         Allocation {
             bytes: self.bytes,
-            size: self.size,
             relocations: Relocations::from_presorted(
                 self.relocations
                     .iter()
@@ -150,7 +145,11 @@ impl Allocation<(), ()> {
 /// Raw accessors. Provide access to otherwise private bytes.
 impl<Tag, Extra> Allocation<Tag, Extra> {
     pub fn len(&self) -> usize {
-        self.size.bytes_usize()
+        self.bytes.len()
+    }
+
+    pub fn size(&self) -> Size {
+        Size::from_bytes(self.len())
     }
 
     /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs
@@ -276,29 +275,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
 
 /// Reading and writing.
 impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
-    /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached
-    /// before a `0` is found.
-    ///
-    /// Most likely, you want to call `Memory::read_c_str` instead of this method.
-    pub fn read_c_str(
-        &self,
-        cx: &impl HasDataLayout,
-        ptr: Pointer<Tag>,
-    ) -> InterpResult<'tcx, &[u8]> {
-        let offset = ptr.offset.bytes_usize();
-        Ok(match self.bytes[offset..].iter().position(|&c| c == 0) {
-            Some(size) => {
-                let size_with_null = Size::from_bytes(size) + Size::from_bytes(1);
-                // Go through `get_bytes` for checks and AllocationExtra hooks.
-                // We read the null, so we include it in the request, but we want it removed
-                // from the result, so we do subslicing.
-                &self.get_bytes(cx, ptr, size_with_null)?[..size]
-            }
-            // This includes the case where `offset` is out-of-bounds to begin with.
-            None => throw_ub!(UnterminatedCString(ptr.erase_tag())),
-        })
-    }
-
     /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
     /// relocation. If `allow_uninit_and_ptr` is `false`, also enforces that the memory in the
     /// given range contains neither relocations nor uninitialized bytes.
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 67440e6e0ed..edf2e539765 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -88,7 +88,7 @@ impl<'tcx> MonoItem<'tcx> {
 
         match *self {
             MonoItem::Fn(ref instance) => {
-                let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
+                let entry_def_id = tcx.entry_fn(()).map(|(id, _)| id);
                 // If this function isn't inlined or otherwise has an extern
                 // indicator, then we'll be creating a globally shared version.
                 if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index a80aa6ad3d8..0edb79fdbc8 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -32,7 +32,6 @@ pub enum UnsafetyViolationDetails {
     UseOfInlineAssembly,
     InitializingTypeWith,
     CastOfPointerToInt,
-    BorrowOfPackedField,
     UseOfMutableStatic,
     UseOfExternStatic,
     DerefOfRawPointer,
@@ -64,11 +63,6 @@ impl UnsafetyViolationDetails {
             CastOfPointerToInt => {
                 ("cast of pointer to int", "casting pointers to integers in constants")
             }
-            BorrowOfPackedField => (
-                "borrow of packed field",
-                "fields of packed structs might be misaligned: dereferencing a misaligned pointer \
-                 or even just creating a misaligned reference is undefined behavior",
-            ),
             UseOfMutableStatic => (
                 "use of mutable static",
                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index fea2aec38a1..70f70788bca 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -20,7 +20,7 @@ rustc_queries! {
     /// This is because the `hir_crate` query gives you access to all other items.
     /// To avoid this fate, do not call `tcx.hir().krate()`; instead,
     /// prefer wrappers like `tcx.visit_all_items_in_krate()`.
-    query hir_crate(key: CrateNum) -> &'tcx Crate<'tcx> {
+    query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
         eval_always
         no_hash
         desc { "get the crate HIR" }
@@ -28,7 +28,7 @@ rustc_queries! {
 
     /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
     /// Avoid calling this query directly.
-    query index_hir(_: CrateNum) -> &'tcx crate::hir::IndexedHir<'tcx> {
+    query index_hir(_: ()) -> &'tcx crate::hir::IndexedHir<'tcx> {
         eval_always
         no_hash
         desc { "index HIR" }
@@ -114,7 +114,7 @@ rustc_queries! {
         cache_on_disk_if { key.is_local() }
     }
 
-    query analysis(key: CrateNum) -> Result<(), ErrorReported> {
+    query analysis(key: ()) -> Result<(), ErrorReported> {
         eval_always
         desc { "running analysis passes on this crate" }
     }
@@ -199,7 +199,7 @@ rustc_queries! {
         desc { "looking up the native libraries of a linked crate" }
     }
 
-    query lint_levels(_: CrateNum) -> LintLevelMap {
+    query lint_levels(_: ()) -> LintLevelMap {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
         desc { "computing the lint levels for items in this crate" }
@@ -223,7 +223,7 @@ rustc_queries! {
     /// Set of all the `DefId`s in this crate that have MIR associated with
     /// them. This includes all the body owners, but also things like struct
     /// constructors.
-    query mir_keys(_: CrateNum) -> FxHashSet<LocalDefId> {
+    query mir_keys(_: ()) -> FxHashSet<LocalDefId> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "getting a list of all mir_keys" }
     }
@@ -335,10 +335,9 @@ rustc_queries! {
 
     /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
     /// MIR pass (assuming the -Zinstrument-coverage option is enabled).
-    query coverageinfo(key: DefId) -> mir::CoverageInfo {
-        desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key) }
+    query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo {
+        desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) }
         storage(ArenaCacheSelector<'tcx>)
-        cache_on_disk_if { key.is_local() }
     }
 
     /// Returns the name of the file that contains the function body, if instrumented for coverage.
@@ -544,7 +543,7 @@ rustc_queries! {
     }
 
     /// Gets a map with the variance of every item; use `item_variance` instead.
-    query crate_variances(_: CrateNum) -> ty::CrateVariancesMap<'tcx> {
+    query crate_variances(_: ()) -> ty::CrateVariancesMap<'tcx> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "computing the variances for items in this crate" }
     }
@@ -555,8 +554,7 @@ rustc_queries! {
     }
 
     /// Maps from thee `DefId` of a type to its (inferred) outlives.
-    query inferred_outlives_crate(_: CrateNum)
-        -> ty::CratePredicatesMap<'tcx> {
+    query inferred_outlives_crate(_: ()) -> ty::CratePredicatesMap<'tcx> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "computing the inferred outlives predicates for items in this crate" }
     }
@@ -695,7 +693,7 @@ rustc_queries! {
             desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
         }
 
-    query typeck_item_bodies(_: CrateNum) -> () {
+    query typeck_item_bodies(_: ()) -> () {
         desc { "type-checking all item bodies" }
     }
 
@@ -754,18 +752,15 @@ rustc_queries! {
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
-    /// (Defined only for `LOCAL_CRATE`.)
-    query crate_inherent_impls(k: CrateNum)
-        -> CrateInherentImpls {
+    query crate_inherent_impls(k: ()) -> CrateInherentImpls {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
-        desc { "all inherent impls defined in crate `{:?}`", k }
+        desc { "all inherent impls defined in crate" }
     }
 
     /// Checks all types in the crate for overlap in their inherent impls. Reports errors.
     /// Not meant to be used directly outside of coherence.
-    /// (Defined only for `LOCAL_CRATE`.)
-    query crate_inherent_impls_overlap_check(_: CrateNum)
+    query crate_inherent_impls_overlap_check(_: ())
         -> () {
         eval_always
         desc { "check for overlap between inherent impls defined in this crate" }
@@ -859,16 +854,16 @@ rustc_queries! {
     }
 
     /// Performs part of the privacy check and computes "access levels".
-    query privacy_access_levels(_: CrateNum) -> &'tcx AccessLevels {
+    query privacy_access_levels(_: ()) -> &'tcx AccessLevels {
         eval_always
         desc { "privacy access levels" }
     }
-    query check_private_in_public(_: CrateNum) -> () {
+    query check_private_in_public(_: ()) -> () {
         eval_always
         desc { "checking for private elements in public interfaces" }
     }
 
-    query reachable_set(_: CrateNum) -> FxHashSet<LocalDefId> {
+    query reachable_set(_: ()) -> FxHashSet<LocalDefId> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "reachability" }
     }
@@ -978,7 +973,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<LocalDefId>> {
+    query all_local_trait_impls(_: ()) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
         desc { "local trait impls" }
     }
 
@@ -1035,6 +1030,10 @@ rustc_queries! {
     query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
         desc { "computing whether `{}` needs drop", env.value }
     }
+    /// Query backing `TyS::has_significant_drop_raw`.
+    query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
+        desc { "computing whether `{}` has a significant drop", env.value }
+    }
 
     /// Query backing `TyS::is_structural_eq_shallow`.
     ///
@@ -1055,6 +1054,17 @@ rustc_queries! {
         cache_on_disk_if { true }
     }
 
+    /// A list of types where the ADT requires drop if and only if any of those types
+    /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor`
+    /// is considered to not be significant. A drop is significant if it is implemented
+    /// by the user or does anything that will have any observable behavior (other than
+    /// freeing up memory). If the ADT is known to have a significant destructor then
+    /// `Err(AlwaysRequiresDrop)` is returned.
+    query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
+        desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) }
+        cache_on_disk_if { false }
+    }
+
     query layout_raw(
         env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
     ) -> Result<&'tcx rustc_target::abi::Layout, ty::layout::LayoutError<'tcx>> {
@@ -1066,9 +1076,7 @@ rustc_queries! {
         desc { "dylib dependency formats of crate" }
     }
 
-    query dependency_formats(_: CrateNum)
-        -> Lrc<crate::middle::dependency_format::Dependencies>
-    {
+    query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
         desc { "get the linkage format of all dependencies" }
     }
 
@@ -1156,10 +1164,10 @@ rustc_queries! {
     query is_reachable_non_generic(def_id: DefId) -> bool {
         desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) }
     }
-    query is_unreachable_local_definition(def_id: DefId) -> bool {
+    query is_unreachable_local_definition(def_id: LocalDefId) -> bool {
         desc { |tcx|
             "checking whether `{}` is reachable from outside the crate",
-            tcx.def_path_str(def_id),
+            tcx.def_path_str(def_id.to_def_id()),
         }
     }
 
@@ -1169,11 +1177,9 @@ rustc_queries! {
     /// added or removed in any upstream crate. Instead use the narrower
     /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
     /// better, `Instance::upstream_monomorphization()`.
-    query upstream_monomorphizations(
-        k: CrateNum
-    ) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+    query upstream_monomorphizations(_: ()) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
         storage(ArenaCacheSelector<'tcx>)
-        desc { "collecting available upstream monomorphizations `{:?}`", k }
+        desc { "collecting available upstream monomorphizations" }
     }
 
     /// Returns the set of upstream monomorphizations available for the
@@ -1216,13 +1222,13 @@ rustc_queries! {
 
     /// Identifies the entry-point (e.g., the `main` function) for a given
     /// crate, returning `None` if there is no entry point (such as for library crates).
-    query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> {
+    query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> {
         desc { "looking up the entry function of a crate" }
     }
-    query plugin_registrar_fn(_: CrateNum) -> Option<DefId> {
+    query plugin_registrar_fn(_: ()) -> Option<LocalDefId> {
         desc { "looking up the plugin registrar for a crate" }
     }
-    query proc_macro_decls_static(_: CrateNum) -> Option<DefId> {
+    query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
         desc { "looking up the derive registrar for a crate" }
     }
     query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
@@ -1349,7 +1355,7 @@ rustc_queries! {
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
-    query get_lib_features(_: CrateNum) -> LibFeatures {
+    query get_lib_features(_: ()) -> LibFeatures {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
         desc { "calculating the lib features map" }
@@ -1359,16 +1365,14 @@ rustc_queries! {
         desc { "calculating the lib features defined in a crate" }
     }
     /// Returns the lang items defined in another crate by loading it from metadata.
-    // FIXME: It is illegal to pass a `CrateNum` other than `LOCAL_CRATE` here, just get rid
-    // of that argument?
-    query get_lang_items(_: CrateNum) -> LanguageItems {
+    query get_lang_items(_: ()) -> LanguageItems {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
         desc { "calculating the lang items map" }
     }
 
     /// Returns all diagnostic items defined in all crates.
-    query all_diagnostic_items(_: CrateNum) -> FxHashMap<Symbol, DefId> {
+    query all_diagnostic_items(_: ()) -> FxHashMap<Symbol, DefId> {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
         desc { "calculating the diagnostic items map" }
@@ -1388,13 +1392,11 @@ rustc_queries! {
     query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] {
         desc { "calculating the missing lang items in a crate" }
     }
-    query visible_parent_map(_: CrateNum)
-        -> DefIdMap<DefId> {
+    query visible_parent_map(_: ()) -> DefIdMap<DefId> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "calculating the visible parent map" }
     }
-    query trimmed_def_paths(_: CrateNum)
-        -> FxHashMap<DefId, Symbol> {
+    query trimmed_def_paths(_: ()) -> FxHashMap<DefId, Symbol> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "calculating trimmed def paths" }
     }
@@ -1406,7 +1408,7 @@ rustc_queries! {
         eval_always
         desc { "looking at the source for a crate" }
     }
-    query postorder_cnums(_: CrateNum) -> &'tcx [CrateNum] {
+    query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "generating a postorder list of CrateNums" }
     }
@@ -1419,8 +1421,7 @@ rustc_queries! {
         eval_always
         desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
-    query maybe_unused_extern_crates(_: CrateNum)
-        -> &'tcx [(LocalDefId, Span)] {
+    query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
         eval_always
         desc { "looking up all possibly unused extern crates" }
     }
@@ -1430,12 +1431,12 @@ rustc_queries! {
         desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
-    query stability_index(_: CrateNum) -> stability::Index<'tcx> {
+    query stability_index(_: ()) -> stability::Index<'tcx> {
         storage(ArenaCacheSelector<'tcx>)
         eval_always
         desc { "calculating the stability index for the local crate" }
     }
-    query all_crate_nums(_: CrateNum) -> &'tcx [CrateNum] {
+    query all_crate_nums(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
@@ -1443,7 +1444,7 @@ rustc_queries! {
     /// A vector of every trait accessible in the whole crate
     /// (i.e., including those from subcrates). This is used only for
     /// error reporting.
-    query all_traits(_: CrateNum) -> &'tcx [DefId] {
+    query all_traits(_: ()) -> &'tcx [DefId] {
         desc { "fetching all foreign and local traits" }
     }
 
@@ -1457,8 +1458,7 @@ rustc_queries! {
         desc { "exported_symbols" }
     }
 
-    query collect_and_partition_mono_items(_: CrateNum)
-        -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
+    query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
         eval_always
         desc { "collect_and_partition_mono_items" }
     }
@@ -1467,8 +1467,7 @@ rustc_queries! {
     }
 
     /// All items participating in code generation together with items inlined into them.
-    query codegened_and_inlined_items(_: CrateNum)
-        -> &'tcx DefIdSet {
+    query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet {
         eval_always
        desc { "codegened_and_inlined_items" }
     }
@@ -1483,11 +1482,11 @@ rustc_queries! {
                 tcx.def_path_str(key)
         }
     }
-    query backend_optimization_level(_: CrateNum) -> OptLevel {
+    query backend_optimization_level(_: ()) -> OptLevel {
         desc { "optimization level used by backend" }
     }
 
-    query output_filenames(_: CrateNum) -> Arc<OutputFilenames> {
+    query output_filenames(_: ()) -> Arc<OutputFilenames> {
         eval_always
         desc { "output_filenames" }
     }
@@ -1663,7 +1662,7 @@ rustc_queries! {
         desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
     }
 
-    query features_query(_: CrateNum) -> &'tcx rustc_feature::Features {
+    query features_query(_: ()) -> &'tcx rustc_feature::Features {
         eval_always
         desc { "looking up enabled feature gates" }
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 7c4229b6db2..dde5cbadbd9 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1218,18 +1218,18 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures {
-        self.get_lib_features(LOCAL_CRATE)
+        self.get_lib_features(())
     }
 
     /// Obtain all lang items of this crate and all dependencies (recursively)
     pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
-        self.get_lang_items(LOCAL_CRATE)
+        self.get_lang_items(())
     }
 
     /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
     /// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
     pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
-        self.all_diagnostic_items(LOCAL_CRATE).get(&name).copied()
+        self.all_diagnostic_items(()).get(&name).copied()
     }
 
     /// Check whether the diagnostic item with the given `name` has the given `DefId`.
@@ -1238,11 +1238,11 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn stability(self) -> &'tcx stability::Index<'tcx> {
-        self.stability_index(LOCAL_CRATE)
+        self.stability_index(())
     }
 
     pub fn crates(self) -> &'tcx [CrateNum] {
-        self.all_crate_nums(LOCAL_CRATE)
+        self.all_crate_nums(())
     }
 
     pub fn allocator_kind(self) -> Option<AllocatorKind> {
@@ -1250,7 +1250,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn features(self) -> &'tcx rustc_feature::Features {
-        self.features_query(LOCAL_CRATE)
+        self.features_query(())
     }
 
     pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
@@ -2623,7 +2623,7 @@ impl<'tcx> TyCtxt<'tcx> {
         lint: &'static Lint,
         mut id: hir::HirId,
     ) -> (Level, LintLevelSource) {
-        let sets = self.lint_levels(LOCAL_CRATE);
+        let sets = self.lint_levels(());
         loop {
             if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
                 return pair;
@@ -2795,10 +2795,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         tcx.crate_name
     };
     providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id);
-    providers.maybe_unused_extern_crates = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        &tcx.maybe_unused_extern_crates[..]
-    };
+    providers.maybe_unused_extern_crates = |tcx, ()| &tcx.maybe_unused_extern_crates[..];
     providers.names_imported_by_glob_use =
         |tcx, id| tcx.arena.alloc(tcx.glob_map.get(&id).cloned().unwrap_or_default());
 
@@ -2815,18 +2812,9 @@ pub fn provide(providers: &mut ty::query::Providers) {
         tcx.stability().local_deprecation_entry(id)
     };
     providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned();
-    providers.all_crate_nums = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        tcx.arena.alloc_slice(&tcx.cstore.crates_untracked())
-    };
-    providers.output_filenames = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        tcx.output_filenames.clone()
-    };
-    providers.features_query = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        tcx.sess.features_untracked()
-    };
+    providers.all_crate_nums = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked());
+    providers.output_filenames = |tcx, ()| tcx.output_filenames.clone();
+    providers.features_query = |tcx, ()| tcx.sess.features_untracked();
     providers.is_panic_runtime = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
         tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index af49533753f..94e325e9e87 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -36,7 +36,7 @@ use rustc_data_structures::sync::{self, par_iter, ParallelIterator};
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
 use rustc_hir::{Constness, Node};
 use rustc_macros::HashStable;
 use rustc_span::hygiene::ExpnId;
@@ -1970,7 +1970,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
     super::util::bug::provide(providers);
     *providers = ty::query::Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
-        all_local_trait_impls: trait_def::all_local_trait_impls,
         type_uninhabited_from: inhabitedness::type_uninhabited_from,
         const_param_default: consts::const_param_default,
         ..*providers
@@ -1984,7 +1983,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
 /// (constructing this map requires touching the entire crate).
 #[derive(Clone, Debug, Default, HashStable)]
 pub struct CrateInherentImpls {
-    pub inherent_impls: DefIdMap<Vec<DefId>>,
+    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index cfb9cfd86f9..76c48597092 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
 use rustc_hir::ItemKind;
 use rustc_session::config::TrimmedDefPaths;
@@ -285,7 +285,7 @@ pub trait PrettyPrinter<'tcx>:
             return Ok((self, false));
         }
 
-        match self.tcx().trimmed_def_paths(LOCAL_CRATE).get(&def_id) {
+        match self.tcx().trimmed_def_paths(()).get(&def_id) {
             None => Ok((self, false)),
             Some(symbol) => {
                 self.write_str(&symbol.as_str())?;
@@ -361,7 +361,7 @@ pub trait PrettyPrinter<'tcx>:
             return Ok((self, false));
         }
 
-        let visible_parent_map = self.tcx().visible_parent_map(LOCAL_CRATE);
+        let visible_parent_map = self.tcx().visible_parent_map(());
 
         let mut cur_def_key = self.tcx().def_key(def_id);
         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
@@ -2302,9 +2302,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
 ///
 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
-fn trimmed_def_paths(tcx: TyCtxt<'_>, crate_num: CrateNum) -> FxHashMap<DefId, Symbol> {
-    assert_eq!(crate_num, LOCAL_CRATE);
-
+fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let mut map = FxHashMap::default();
 
     if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
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 f220d83b0c7..a688b816e9a 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -579,7 +579,7 @@ impl<'sess> OnDiskCache<'sess> {
     ) -> IndexVec<CrateNum, Option<CrateNum>> {
         tcx.dep_graph.with_ignore(|| {
             let current_cnums = tcx
-                .all_crate_nums(LOCAL_CRATE)
+                .all_crate_nums(())
                 .iter()
                 .map(|&cnum| {
                     let crate_name = tcx.original_crate_name(cnum).to_string();
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index e9b8883f29a..79166472acf 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -4,14 +4,13 @@ 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, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_hir::definitions::DefPathHash;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorReported;
 use rustc_macros::HashStable;
-use std::collections::BTreeMap;
 
 /// A trait's definition with type information.
 #[derive(HashStable)]
@@ -209,14 +208,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-// Query provider for `all_local_trait_impls`.
-pub(super) fn all_local_trait_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    krate: CrateNum,
-) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
-    &tcx.hir_crate(krate).trait_impls
-}
-
 // Query provider for `trait_impls_of`.
 pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls {
     let mut impls = TraitImpls::default();
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e365928c15f..7bf69b9e637 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -791,6 +791,39 @@ impl<'tcx> ty::TyS<'tcx> {
         }
     }
 
+    /// Checks if `ty` has has a significant drop.
+    ///
+    /// Note that this method can return false even if `ty` has a destructor
+    /// attached; even if that is the case then the adt has been marked with
+    /// the attribute `rustc_insignificant_dtor`.
+    ///
+    /// Note that this method is used to check for change in drop order for
+    /// 2229 drop reorder migration analysis.
+    #[inline]
+    pub fn has_significant_drop(
+        &'tcx self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        // Avoid querying in simple cases.
+        match needs_drop_components(self, &tcx.data_layout) {
+            Err(AlwaysRequiresDrop) => true,
+            Ok(components) => {
+                let query_ty = match *components {
+                    [] => return false,
+                    // If we've got a single component, call the query with that
+                    // to increase the chance that we hit the query cache.
+                    [component_ty] => component_ty,
+                    _ => self,
+                };
+                // This doesn't depend on regions, so try to minimize distinct
+                // query keys used.
+                let erased = tcx.normalize_erasing_regions(param_env, query_ty);
+                tcx.has_significant_drop_raw(param_env.and(erased))
+            }
+        }
+    }
+
     /// Returns `true` if equality for this type is both reflexive and structural.
     ///
     /// Reflexive equality for a type is indicated by an `Eq` impl for that type.
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
index bbd512fd360..f4d78ac04cb 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
@@ -1241,7 +1241,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// it. However, it works pretty well in practice. In particular,
     /// this is needed to deal with projection outlives bounds like
     ///
-    /// ```ignore (internal compiler representation so lifetime syntax is invalid)
+    /// ```text
     /// <T as Foo<'0>>::Item: '1
     /// ```
     ///
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index 994b403abf3..1bfbb843114 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -137,10 +137,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                         self.loc,
                         InteriorOfSliceOrArray {
                             ty: place_ty,
-                            is_index: match elem {
-                                ProjectionElem::Index(..) => true,
-                                _ => false,
-                            },
+                            is_index: matches!(elem, ProjectionElem::Index(..)),
                         },
                     ));
                 }
diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs
index 1aaa56403f4..5200e4aa90d 100644
--- a/compiler/rustc_mir/src/interpret/memory.rs
+++ b/compiler/rustc_mir/src/interpret/memory.rs
@@ -244,7 +244,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         let new_ptr = self.allocate(new_size, new_align, kind);
         let old_size = match old_size_and_align {
             Some((size, _align)) => size,
-            None => self.get_raw(ptr.alloc_id)?.size,
+            None => self.get_raw(ptr.alloc_id)?.size(),
         };
         self.copy(ptr, new_ptr, old_size.min(new_size), /*nonoverlapping*/ true)?;
         self.deallocate(ptr, old_size_and_align, kind)?;
@@ -306,11 +306,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             );
         }
         if let Some((size, align)) = old_size_and_align {
-            if size != alloc.size || align != alloc.align {
+            if size != alloc.size() || align != alloc.align {
                 throw_ub_format!(
                     "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}",
                     ptr.alloc_id,
-                    alloc.size.bytes(),
+                    alloc.size().bytes(),
                     alloc.align.bytes(),
                     size.bytes(),
                     align.bytes(),
@@ -319,11 +319,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         }
 
         // Let the machine take some extra action
-        let size = alloc.size;
+        let size = alloc.size();
         AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?;
 
         // Don't forget to remember size and align of this now-dead allocation
-        let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size, alloc.align));
+        let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size(), alloc.align));
         if old.is_some() {
             bug!("Nothing can be deallocated twice");
         }
@@ -586,7 +586,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         // a) cause cycles in case `id` refers to a static
         // b) duplicate a global's allocation in miri
         if let Some((_, alloc)) = self.alloc_map.get(id) {
-            return Ok((alloc.size, alloc.align));
+            return Ok((alloc.size(), alloc.align));
         }
 
         // # Function pointers
@@ -614,7 +614,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             Some(GlobalAlloc::Memory(alloc)) => {
                 // Need to duplicate the logic here, because the global allocations have
                 // different associated types than the interpreter-local ones.
-                Ok((alloc.size, alloc.align))
+                Ok((alloc.size(), alloc.align))
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
             // The rest must be dead.
@@ -804,41 +804,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         self.get_raw(ptr.alloc_id)?.get_bytes(self, ptr, size)
     }
 
-    /// Reads a 0-terminated sequence of bytes from memory. Returns them as a slice.
-    ///
-    /// Performs appropriate bounds checks.
-    pub fn read_c_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, &[u8]> {
-        let ptr = self.force_ptr(ptr)?; // We need to read at least 1 byte, so we *need* a ptr.
-        self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr)
-    }
-
-    /// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec<u16>.
-    /// Terminator 0x0000 is not included in the returned Vec<u16>.
-    ///
-    /// Performs appropriate bounds checks.
-    pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, Vec<u16>> {
-        let size_2bytes = Size::from_bytes(2);
-        let align_2bytes = Align::from_bytes(2).unwrap();
-        // We need to read at least 2 bytes, so we *need* a ptr.
-        let mut ptr = self.force_ptr(ptr)?;
-        let allocation = self.get_raw(ptr.alloc_id)?;
-        let mut u16_seq = Vec::new();
-
-        loop {
-            ptr = self
-                .check_ptr_access(ptr.into(), size_2bytes, align_2bytes)?
-                .expect("cannot be a ZST");
-            let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?;
-            if single_u16 != 0x0000 {
-                u16_seq.push(single_u16);
-                ptr = ptr.offset(size_2bytes, self)?;
-            } else {
-                break;
-            }
-        }
-        Ok(u16_seq)
-    }
-
     /// Writes the given stream of bytes into memory.
     ///
     /// Performs appropriate bounds checks.
@@ -866,46 +831,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
     }
 
-    /// Writes the given stream of u16s into memory.
-    ///
-    /// Performs appropriate bounds checks.
-    pub fn write_u16s(
-        &mut self,
-        ptr: Scalar<M::PointerTag>,
-        src: impl IntoIterator<Item = u16>,
-    ) -> InterpResult<'tcx> {
-        let mut src = src.into_iter();
-        let (lower, upper) = src.size_hint();
-        let len = upper.expect("can only write bounded iterators");
-        assert_eq!(lower, len, "can only write iterators with a precise length");
-
-        let size = Size::from_bytes(lower);
-        let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? {
-            Some(ptr) => ptr,
-            None => {
-                // zero-sized access
-                assert_matches!(
-                    src.next(),
-                    None,
-                    "iterator said it was empty but returned an element"
-                );
-                return Ok(());
-            }
-        };
-        let tcx = self.tcx;
-        let allocation = self.get_raw_mut(ptr.alloc_id)?;
-
-        for idx in 0..len {
-            let val = Scalar::from_u16(
-                src.next().expect("iterator was shorter than it said it would be"),
-            );
-            let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
-            allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
-        }
-        assert_matches!(src.next(), None, "iterator was longer than it said it would be");
-        Ok(())
-    }
-
     /// Expects the caller to have checked bounds and alignment.
     pub fn copy(
         &mut self,
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs
index 4aa1360d535..a7fcb41f74a 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_mir/src/interpret/terminator.rs
@@ -3,7 +3,10 @@ use std::convert::TryFrom;
 
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::Instance;
-use rustc_middle::{mir, ty};
+use rustc_middle::{
+    mir,
+    ty::{self, Ty},
+};
 use rustc_target::abi::{self, LayoutOf as _};
 use rustc_target::spec::abi::Abi;
 
@@ -228,15 +231,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
 
         // ABI check
-        {
-            let callee_abi = {
-                let instance_ty = instance.ty(*self.tcx, self.param_env);
-                match instance_ty.kind() {
-                    ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
-                    ty::Closure(..) => Abi::RustCall,
-                    ty::Generator(..) => Abi::Rust,
-                    _ => span_bug!(self.cur_span(), "unexpected callee ty: {:?}", instance_ty),
-                }
+        let check_abi = |this: &Self, instance_ty: Ty<'tcx>| -> InterpResult<'tcx> {
+            let callee_abi = match instance_ty.kind() {
+                ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(),
+                ty::Closure(..) => Abi::RustCall,
+                ty::Generator(..) => Abi::Rust,
+                _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty),
             };
             let normalize_abi = |abi| match abi {
                 Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic =>
@@ -253,10 +253,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     caller_abi.name()
                 )
             }
-        }
+            Ok(())
+        };
 
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
+                check_abi(self, instance.ty(*self.tcx, self.param_env))?;
                 assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
                 M::call_intrinsic(self, instance, args, ret, unwind)
             }
@@ -274,6 +276,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         None => return Ok(()),
                     };
 
+                // Check against the ABI of the MIR body we are calling (not the ABI of `instance`;
+                // these can differ when `find_mir_or_eval_fn` does something clever like resolve
+                // exported symbol names).
+                check_abi(self, self.tcx.type_of(body.source.def_id()))?;
+
                 self.push_stack_frame(
                     instance,
                     body,
diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs
index 6e6e64d25ac..83b0d0528f7 100644
--- a/compiler/rustc_mir/src/interpret/validity.rs
+++ b/compiler/rustc_mir/src/interpret/validity.rs
@@ -833,6 +833,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)),
                     self.path,
                     err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" },
+                    err_unsup!(ReadPointerAsBytes) => { "a pointer in `str`" },
                 );
             }
             ty::Array(tys, ..) | ty::Slice(tys)
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs
index e4ad92eb1b1..ef79f36b3b5 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_mir/src/monomorphize/collector.rs
@@ -184,7 +184,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
 use rustc_errors::{ErrorReported, FatalError};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
@@ -322,7 +322,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
     let mut roots = Vec::new();
 
     {
-        let entry_fn = tcx.entry_fn(LOCAL_CRATE);
+        let entry_fn = tcx.entry_fn(());
 
         debug!("collect_roots: entry_fn = {:?}", entry_fn);
 
@@ -468,7 +468,7 @@ fn shrunk_instance_name(
             after = &s[positions().rev().nth(after).unwrap_or(0)..],
         );
 
-        let path = tcx.output_filenames(LOCAL_CRATE).temp_path_ext("long-type.txt", None);
+        let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None);
         let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
 
         (shrunk, written_to_path)
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
index edd46310f20..541c825416c 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
@@ -451,7 +451,9 @@ fn mono_item_visibility(
     let is_generic = instance.substs.non_erasable_generics().next().is_some();
 
     // Upstream `DefId` instances get different handling than local ones.
-    if !def_id.is_local() {
+    let def_id = if let Some(def_id) = def_id.as_local() {
+        def_id
+    } else {
         return if export_generics && is_generic {
             // If it is a upstream monomorphization and we export generics, we must make
             // it available to downstream crates.
@@ -460,7 +462,7 @@ fn mono_item_visibility(
         } else {
             Visibility::Hidden
         };
-    }
+    };
 
     if is_generic {
         if export_generics {
@@ -470,7 +472,7 @@ fn mono_item_visibility(
             } else {
                 // This instance might be useful in a downstream crate.
                 *can_be_internalized = false;
-                default_visibility(tcx, def_id, true)
+                default_visibility(tcx, def_id.to_def_id(), true)
             }
         } else {
             // We are not exporting generics or the definition is not reachable
@@ -481,10 +483,10 @@ fn mono_item_visibility(
         // If this isn't a generic function then we mark this a `Default` if
         // this is a reachable item, meaning that it's a symbol other crates may
         // access when they link to us.
-        if tcx.is_reachable_non_generic(def_id) {
+        if tcx.is_reachable_non_generic(def_id.to_def_id()) {
             *can_be_internalized = false;
             debug_assert!(!is_generic);
-            return default_visibility(tcx, def_id, false);
+            return default_visibility(tcx, def_id.to_def_id(), false);
         }
 
         // If this isn't reachable then we're gonna tag this with `Hidden`
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
index 333cb301590..6ed0ab8be41 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
@@ -97,7 +97,7 @@ mod merging;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync;
-use rustc_hir::def_id::{CrateNum, DefIdSet, LOCAL_CRATE};
+use rustc_hir::def_id::DefIdSet;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{CodegenUnit, Linkage};
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -311,10 +311,8 @@ where
 
 fn collect_and_partition_mono_items<'tcx>(
     tcx: TyCtxt<'tcx>,
-    cnum: CrateNum,
+    (): (),
 ) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
-    assert_eq!(cnum, LOCAL_CRATE);
-
     let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
         Some(ref s) => {
             let mode_string = s.to_lowercase();
@@ -426,8 +424,8 @@ fn collect_and_partition_mono_items<'tcx>(
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
-fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx DefIdSet {
-    let (items, cgus) = tcx.collect_and_partition_mono_items(cnum);
+fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
+    let (items, cgus) = tcx.collect_and_partition_mono_items(());
     let mut visited = DefIdSet::default();
     let mut result = items.clone();
 
@@ -455,12 +453,12 @@ pub fn provide(providers: &mut Providers) {
     providers.codegened_and_inlined_items = codegened_and_inlined_items;
 
     providers.is_codegened_item = |tcx, def_id| {
-        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+        let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
         all_mono_items.contains(&def_id)
     };
 
     providers.codegen_unit = |tcx, name| {
-        let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
+        let (_, all) = tcx.collect_and_partition_mono_items(());
         all.iter()
             .find(|cgu| cgu.name() == name)
             .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index ffeaaf60a30..16f5f14f563 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -141,12 +141,20 @@ impl NonConstOp for FnPtrCast {
 pub struct Generator(pub hir::GeneratorKind);
 impl NonConstOp for Generator {
     fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
-        Status::Forbidden
+        if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
+            Status::Unstable(sym::const_async_blocks)
+        } else {
+            Status::Forbidden
+        }
     }
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
         let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
-        ccx.tcx.sess.struct_span_err(span, &msg)
+        if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
+            feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg)
+        } else {
+            ccx.tcx.sess.struct_span_err(span, &msg)
+        }
     }
 }
 
diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs
index 48361483099..2397d627880 100644
--- a/compiler/rustc_mir/src/transform/coverage/debug.rs
+++ b/compiler/rustc_mir/src/transform/coverage/debug.rs
@@ -120,6 +120,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
 use rustc_middle::ty::TyCtxt;
+use rustc_span::Span;
 
 use std::iter;
 use std::lazy::SyncOnceCell;
@@ -636,6 +637,7 @@ pub(super) fn dump_coverage_spanview(
     mir_body: &mir::Body<'tcx>,
     basic_coverage_blocks: &CoverageGraph,
     pass_name: &str,
+    body_span: Span,
     coverage_spans: &Vec<CoverageSpan>,
 ) {
     let mir_source = mir_body.source;
@@ -647,7 +649,7 @@ pub(super) fn dump_coverage_spanview(
     let crate_name = tcx.crate_name(def_id.krate);
     let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate();
     let title = format!("{}.{} - Coverage Spans", crate_name, item_name);
-    spanview::write_document(tcx, def_id, span_viewables, &title, &mut file)
+    spanview::write_document(tcx, body_span, span_viewables, &title, &mut file)
         .expect("Unexpected IO error dumping coverage spans as HTML");
 }
 
diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs
index 918d6ee4b0c..71c244fdd4a 100644
--- a/compiler/rustc_mir/src/transform/coverage/mod.rs
+++ b/compiler/rustc_mir/src/transform/coverage/mod.rs
@@ -95,7 +95,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
 
         trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
         Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
-        trace!("InstrumentCoverage starting for {:?}", mir_source.def_id());
+        trace!("InstrumentCoverage done for {:?}", mir_source.def_id());
     }
 }
 
@@ -116,25 +116,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         let def_id = mir_body.source.def_id();
         let (some_fn_sig, hir_body) = fn_sig_and_body(tcx, def_id);
 
-        let mut body_span = hir_body.value.span;
-
-        if tcx.is_closure(def_id) {
-            // If the MIR function is a closure, and if the closure body span
-            // starts from a macro, but it's content is not in that macro, try
-            // to find a non-macro callsite, and instrument the spans there
-            // instead.
-            loop {
-                let expn_data = body_span.ctxt().outer_expn_data();
-                if expn_data.is_root() {
-                    break;
-                }
-                if let ExpnKind::Macro { .. } = expn_data.kind {
-                    body_span = expn_data.call_site;
-                } else {
-                    break;
-                }
-            }
-        }
+        let body_span = get_body_span(tcx, hir_body, mir_body);
 
         let source_file = source_map.lookup_source_file(body_span.lo());
         let fn_sig_span = match some_fn_sig.filter(|fn_sig| {
@@ -144,6 +126,15 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()),
             None => body_span.shrink_to_lo(),
         };
+
+        debug!(
+            "instrumenting {}: {:?}, fn sig span: {:?}, body span: {:?}",
+            if tcx.is_closure(def_id) { "closure" } else { "function" },
+            def_id,
+            fn_sig_span,
+            body_span
+        );
+
         let function_source_hash = hash_mir_source(tcx, hir_body);
         let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
         Self {
@@ -160,19 +151,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
     fn inject_counters(&'a mut self) {
         let tcx = self.tcx;
-        let source_map = tcx.sess.source_map();
         let mir_source = self.mir_body.source;
         let def_id = mir_source.def_id();
         let fn_sig_span = self.fn_sig_span;
         let body_span = self.body_span;
 
-        debug!(
-            "instrumenting {:?}, fn sig span: {}, body span: {}",
-            def_id,
-            source_map.span_to_diagnostic_string(fn_sig_span),
-            source_map.span_to_diagnostic_string(body_span)
-        );
-
         let mut graphviz_data = debug::GraphvizData::new();
         let mut debug_used_expressions = debug::UsedExpressions::new();
 
@@ -204,6 +187,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                 self.mir_body,
                 &self.basic_coverage_blocks,
                 self.pass_name,
+                body_span,
                 &coverage_spans,
             );
         }
@@ -560,6 +544,35 @@ fn fn_sig_and_body<'tcx>(
     (hir::map::fn_sig(hir_node), tcx.hir().body(fn_body_id))
 }
 
+fn get_body_span<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    hir_body: &rustc_hir::Body<'tcx>,
+    mir_body: &mut mir::Body<'tcx>,
+) -> Span {
+    let mut body_span = hir_body.value.span;
+    let def_id = mir_body.source.def_id();
+
+    if tcx.is_closure(def_id) {
+        // If the MIR function is a closure, and if the closure body span
+        // starts from a macro, but it's content is not in that macro, try
+        // to find a non-macro callsite, and instrument the spans there
+        // instead.
+        loop {
+            let expn_data = body_span.ctxt().outer_expn_data();
+            if expn_data.is_root() {
+                break;
+            }
+            if let ExpnKind::Macro { .. } = expn_data.kind {
+                body_span = expn_data.call_site;
+            } else {
+                break;
+            }
+        }
+    }
+
+    body_span
+}
+
 fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 {
     let mut hcx = tcx.create_no_span_stable_hashing_context();
     hash(&mut hcx, &hir_body.value).to_smaller_hash()
diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs
index 2ba9d1bdc0c..760f16eae6b 100644
--- a/compiler/rustc_mir/src/transform/coverage/query.rs
+++ b/compiler/rustc_mir/src/transform/coverage/query.rs
@@ -120,8 +120,8 @@ impl CoverageVisitor {
     }
 }
 
-fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo {
-    let mir_body = mir_body(tcx, def_id);
+fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> CoverageInfo {
+    let mir_body = tcx.instance_mir(instance_def);
 
     let mut coverage_visitor = CoverageVisitor {
         // num_counters always has at least the `ZERO` counter.
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs
index 444b4e2ca19..f62171b3c53 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir/src/transform/coverage/spans.rs
@@ -530,17 +530,25 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                     .iter()
                     .enumerate()
                     .filter_map(move |(index, statement)| {
-                        filtered_statement_span(statement, self.body_span).map(
-                            |(span, expn_span)| {
-                                CoverageSpan::for_statement(
-                                    statement, span, expn_span, bcb, bb, index,
-                                )
-                            },
-                        )
+                        filtered_statement_span(statement).map(|span| {
+                            CoverageSpan::for_statement(
+                                statement,
+                                function_source_span(span, self.body_span),
+                                span,
+                                bcb,
+                                bb,
+                                index,
+                            )
+                        })
                     })
-                    .chain(filtered_terminator_span(data.terminator(), self.body_span).map(
-                        |(span, expn_span)| CoverageSpan::for_terminator(span, expn_span, bcb, bb),
-                    ))
+                    .chain(filtered_terminator_span(data.terminator()).map(|span| {
+                        CoverageSpan::for_terminator(
+                            function_source_span(span, self.body_span),
+                            span,
+                            bcb,
+                            bb,
+                        )
+                    }))
             })
             .collect()
     }
@@ -795,13 +803,9 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     }
 }
 
-/// See `function_source_span()` for a description of the two returned spans.
-/// If the MIR `Statement` is not contributive to computing coverage spans,
-/// returns `None`.
-pub(super) fn filtered_statement_span(
-    statement: &'a Statement<'tcx>,
-    body_span: Span,
-) -> Option<(Span, Span)> {
+/// If the MIR `Statement` has a span contributive to computing coverage spans,
+/// return it; otherwise return `None`.
+pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option<Span> {
     match statement.kind {
         // These statements have spans that are often outside the scope of the executed source code
         // for their parent `BasicBlock`.
@@ -838,18 +842,14 @@ pub(super) fn filtered_statement_span(
         | StatementKind::LlvmInlineAsm(_)
         | StatementKind::Retag(_, _)
         | StatementKind::AscribeUserType(_, _) => {
-            Some(function_source_span(statement.source_info.span, body_span))
+            Some(statement.source_info.span)
         }
     }
 }
 
-/// See `function_source_span()` for a description of the two returned spans.
-/// If the MIR `Terminator` is not contributive to computing coverage spans,
-/// returns `None`.
-pub(super) fn filtered_terminator_span(
-    terminator: &'a Terminator<'tcx>,
-    body_span: Span,
-) -> Option<(Span, Span)> {
+/// If the MIR `Terminator` has a span contributive to computing coverage spans,
+/// return it; otherwise return `None`.
+pub(super) fn filtered_terminator_span(terminator: &'a Terminator<'tcx>) -> Option<Span> {
     match terminator.kind {
         // These terminators have spans that don't positively contribute to computing a reasonable
         // span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -873,7 +873,7 @@ pub(super) fn filtered_terminator_span(
                     span = span.with_lo(constant.span.lo());
                 }
             }
-            Some(function_source_span(span, body_span))
+            Some(span)
         }
 
         // Retain spans from all other terminators
@@ -884,28 +884,20 @@ pub(super) fn filtered_terminator_span(
         | TerminatorKind::GeneratorDrop
         | TerminatorKind::FalseUnwind { .. }
         | TerminatorKind::InlineAsm { .. } => {
-            Some(function_source_span(terminator.source_info.span, body_span))
+            Some(terminator.source_info.span)
         }
     }
 }
 
-/// Returns two spans from the given span (the span associated with a
-/// `Statement` or `Terminator`):
-///
-///   1. An extrapolated span (pre-expansion[^1]) corresponding to a range within
-///      the function's body source. This span is guaranteed to be contained
-///      within, or equal to, the `body_span`. If the extrapolated span is not
-///      contained within the `body_span`, the `body_span` is returned.
-///   2. The actual `span` value from the `Statement`, before expansion.
-///
-/// Only the first span is used when computing coverage code regions. The second
-/// span is useful if additional expansion data is needed (such as to look up
-/// the macro name for a composed span within that macro).)
+/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range
+/// within the function's body source. This span is guaranteed to be contained
+/// within, or equal to, the `body_span`. If the extrapolated span is not
+/// contained within the `body_span`, the `body_span` is returned.
 ///
-/// [^1]Expansions result from Rust syntax including macros, syntactic
-/// sugar, etc.).
+/// [^1]Expansions result from Rust syntax including macros, syntactic sugar,
+/// etc.).
 #[inline]
-fn function_source_span(span: Span, body_span: Span) -> (Span, Span) {
+pub(super) fn function_source_span(span: Span, body_span: Span) -> Span {
     let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
-    (if body_span.contains(original_span) { original_span } else { body_span }, span)
+    if body_span.contains(original_span) { original_span } else { body_span }
 }
diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs
index 9b84173c8a2..b04c2d542d4 100644
--- a/compiler/rustc_mir/src/transform/coverage/tests.rs
+++ b/compiler/rustc_mir/src/transform/coverage/tests.rs
@@ -683,12 +683,10 @@ fn test_make_bcb_counters() {
         let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
         let mut coverage_spans = Vec::new();
         for (bcb, data) in basic_coverage_blocks.iter_enumerated() {
-            if let Some((span, expn_span)) =
-                spans::filtered_terminator_span(data.terminator(&mir_body), body_span)
-            {
+            if let Some(span) = spans::filtered_terminator_span(data.terminator(&mir_body)) {
                 coverage_spans.push(spans::CoverageSpan::for_terminator(
+                    spans::function_source_span(span, body_span),
                     span,
-                    expn_span,
                     bcb,
                     data.last_bb(),
                 ));
diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
index f7ea9faec47..7934d4ba849 100644
--- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
+++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
@@ -170,10 +170,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
 }
 
 fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool {
-    match terminator.kind {
-        TerminatorKind::SwitchInt { .. } => true,
-        _ => false,
-    }
+    matches!(terminator.kind, TerminatorKind::SwitchInt { .. })
 }
 
 struct Helper<'a, 'tcx> {
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 5c49ee69edc..2201223e13e 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -3,7 +3,7 @@ use required_consts::RequiredConstsVisitor;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
@@ -98,14 +98,13 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    tcx.mir_keys(def_id.krate).contains(&def_id.expect_local())
+    let def_id = def_id.expect_local();
+    tcx.mir_keys(()).contains(&def_id)
 }
 
 /// Finds the full set of `DefId`s within the current crate that have
 /// MIR associated with them.
-fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet<LocalDefId> {
-    assert_eq!(krate, LOCAL_CRATE);
-
+fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
     let mut set = FxHashSet::default();
 
     // All body-owners have MIR associated with them.
diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs
index b42543c04eb..89fddc95c98 100644
--- a/compiler/rustc_mir/src/transform/simplify_try.rs
+++ b/compiler/rustc_mir/src/transform/simplify_try.rs
@@ -628,10 +628,7 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
                     // But `asm!(...)` could abort the program,
                     // so we cannot assume that the `unreachable` terminator itself is reachable.
                     // FIXME(Centril): use a normalization pass instead of a check.
-                    || bb.statements.iter().any(|stmt| match stmt.kind {
-                        StatementKind::LlvmInlineAsm(..) => true,
-                        _ => false,
-                    })
+                    || bb.statements.iter().any(|stmt| matches!(stmt.kind, StatementKind::LlvmInlineAsm(..)))
                     })
                     .peekable();
 
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs
index 955e85c944a..c4e1e184ac5 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_mir/src/util/pretty.rs
@@ -10,7 +10,7 @@ use super::spanview::write_mir_fn_spanview;
 use crate::transform::MirSource;
 use either::Either;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{
     read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer,
@@ -776,8 +776,8 @@ pub struct RenderAllocation<'a, 'tcx, Tag, Extra> {
 impl<Tag: Copy + Debug, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
     fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let RenderAllocation { tcx, alloc } = *self;
-        write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?;
-        if alloc.size == Size::ZERO {
+        write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?;
+        if alloc.size() == Size::ZERO {
             // We are done.
             return write!(w, " {{}}");
         }
@@ -822,9 +822,9 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
     w: &mut dyn std::fmt::Write,
     prefix: &str,
 ) -> std::fmt::Result {
-    let num_lines = alloc.size.bytes_usize().saturating_sub(BYTES_PER_LINE);
+    let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE);
     // Number of chars needed to represent all line numbers.
-    let pos_width = format!("{:x}", alloc.size.bytes()).len();
+    let pos_width = format!("{:x}", alloc.size().bytes()).len();
 
     if num_lines > 0 {
         write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?;
@@ -845,7 +845,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
         }
     };
 
-    while i < alloc.size {
+    while i < alloc.size() {
         // The line start already has a space. While we could remove that space from the line start
         // printing and unconditionally print a space here, that would cause the single-line case
         // to have a single space before it, which looks weird.
@@ -929,7 +929,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
             i += Size::from_bytes(1);
         }
         // Print a new line header if the next line still has some bytes to print.
-        if i == line_start + Size::from_bytes(BYTES_PER_LINE) && i != alloc.size {
+        if i == line_start + Size::from_bytes(BYTES_PER_LINE) && i != alloc.size() {
             line_start = write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?;
             ascii.clear();
         }
@@ -1020,6 +1020,6 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> {
     if let Some(i) = single {
         vec![i]
     } else {
-        tcx.mir_keys(LOCAL_CRATE).iter().map(|def_id| def_id.to_def_id()).collect()
+        tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect()
     }
 }
diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_mir/src/util/spanview.rs
index 2103f2f0934..42683dac426 100644
--- a/compiler/rustc_mir/src/util/spanview.rs
+++ b/compiler/rustc_mir/src/util/spanview.rs
@@ -131,7 +131,7 @@ where
             }
         }
     }
-    write_document(tcx, def_id, span_viewables, title, w)?;
+    write_document(tcx, fn_span(tcx, def_id), span_viewables, title, w)?;
     Ok(())
 }
 
@@ -139,7 +139,7 @@ where
 /// list `SpanViewable`s.
 pub fn write_document<'tcx, W>(
     tcx: TyCtxt<'tcx>,
-    def_id: DefId,
+    spanview_span: Span,
     mut span_viewables: Vec<SpanViewable>,
     title: &str,
     w: &mut W,
@@ -147,16 +147,16 @@ pub fn write_document<'tcx, W>(
 where
     W: Write,
 {
-    let fn_span = fn_span(tcx, def_id);
-    let mut from_pos = fn_span.lo();
-    let end_pos = fn_span.hi();
+    let mut from_pos = spanview_span.lo();
+    let end_pos = spanview_span.hi();
     let source_map = tcx.sess.source_map();
     let start = source_map.lookup_char_pos(from_pos);
     let indent_to_initial_start_col = " ".repeat(start.col.to_usize());
     debug!(
-        "fn_span source is:\n{}{}",
+        "spanview_span={:?}; source is:\n{}{}",
+        spanview_span,
         indent_to_initial_start_col,
-        source_map.span_to_snippet(fn_span).expect("function should have printable source")
+        source_map.span_to_snippet(spanview_span).expect("function should have printable source")
     );
     writeln!(w, "{}", HEADER)?;
     writeln!(w, "<title>{}</title>", title)?;
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 933362578f9..32799cbf4c7 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -64,38 +64,30 @@ impl<'tcx> UnsafetyVisitor<'tcx> {
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
                 // unsafe_op_in_unsafe_fn is disallowed
-                if kind == BorrowOfPackedField {
-                    // FIXME handle borrows of packed fields
-                } else {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0133,
-                        "{} is unsafe and requires unsafe block",
-                        description,
-                    )
-                    .span_label(span, description)
-                    .note(note)
-                    .emit();
-                }
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0133,
+                    "{} is unsafe and requires unsafe block",
+                    description,
+                )
+                .span_label(span, description)
+                .note(note)
+                .emit();
             }
             SafetyContext::Safe => {
-                if kind == BorrowOfPackedField {
-                    // FIXME handle borrows of packed fields
-                } else {
-                    let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
-                    struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0133,
-                        "{} is unsafe and requires unsafe{} block",
-                        description,
-                        fn_sugg,
-                    )
-                    .span_label(span, description)
-                    .note(note)
-                    .emit();
-                }
+                let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0133,
+                    "{} is unsafe and requires unsafe{} block",
+                    description,
+                    fn_sugg,
+                )
+                .span_label(span, description)
+                .note(note)
+                .emit();
             }
         }
     }
@@ -153,6 +145,9 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> {
                     self.requires_unsafe(expr.span, CallToUnsafeFunction);
                 }
             }
+            ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
+                self.requires_unsafe(expr.span, UseOfInlineAssembly);
+            }
             _ => {}
         }
 
@@ -194,15 +189,12 @@ impl BodyUnsafety {
 #[derive(Clone, Copy, PartialEq)]
 enum UnsafeOpKind {
     CallToUnsafeFunction,
-    #[allow(dead_code)] // FIXME
     UseOfInlineAssembly,
     #[allow(dead_code)] // FIXME
     InitializingTypeWith,
     #[allow(dead_code)] // FIXME
     CastOfPointerToInt,
     #[allow(dead_code)] // FIXME
-    BorrowOfPackedField,
-    #[allow(dead_code)] // FIXME
     UseOfMutableStatic,
     #[allow(dead_code)] // FIXME
     UseOfExternStatic,
@@ -242,11 +234,6 @@ impl UnsafeOpKind {
             CastOfPointerToInt => {
                 ("cast of pointer to int", "casting pointers to integers in constants")
             }
-            BorrowOfPackedField => (
-                "borrow of packed field",
-                "fields of packed structs might be misaligned: dereferencing a misaligned pointer \
-                 or even just creating a misaligned reference is undefined behavior",
-            ),
             UseOfMutableStatic => (
                 "use of mutable static",
                 "mutable statics can be mutated by multiple threads: aliasing violations or data \
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index b2b578f1ed4..c64fab0507c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> {
         Ok((class_name, ItemKind::Union(vdata, generics)))
     }
 
-    fn parse_record_struct_body(
+    pub(super) fn parse_record_struct_body(
         &mut self,
         adt_ty: &str,
     ) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
@@ -1470,19 +1470,25 @@ impl<'a> Parser<'a> {
     fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
         let (ident, is_raw) = self.ident_or_err()?;
         if !is_raw && ident.is_reserved() {
-            let err = if self.check_fn_front_matter(false) {
-                let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
-                let mut err = self.struct_span_err(
-                    lo.to(self.prev_token.span),
-                    &format!("functions are not allowed in {} definitions", adt_ty),
-                );
-                err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
-                err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                err
+            if ident.name == kw::Underscore {
+                self.sess.gated_spans.gate(sym::unnamed_fields, lo);
             } else {
-                self.expected_ident_found()
-            };
-            return Err(err);
+                let err = if self.check_fn_front_matter(false) {
+                    let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
+                    let mut err = self.struct_span_err(
+                        lo.to(self.prev_token.span),
+                        &format!("functions are not allowed in {} definitions", adt_ty),
+                    );
+                    err.help(
+                        "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
+                    );
+                    err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+                    err
+                } else {
+                    self.expected_ident_found()
+                };
+                return Err(err);
+            }
         }
         self.bump();
         Ok(ident)
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 35cfaae13a4..4c2bc6ebf31 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1065,24 +1065,11 @@ impl<'a> Parser<'a> {
             } else if !delimited_only {
                 if self.eat(&token::Eq) {
                     let eq_span = self.prev_token.span;
-                    let mut is_interpolated_expr = false;
-                    if let token::Interpolated(nt) = &self.token.kind {
-                        if let token::NtExpr(..) = **nt {
-                            is_interpolated_expr = true;
-                        }
-                    }
 
                     // Collect tokens because they are used during lowering to HIR.
                     let expr = self.parse_expr_force_collect()?;
                     let span = expr.span;
 
-                    match &expr.kind {
-                        // Not gated to support things like `doc = $expr` that work on stable.
-                        _ if is_interpolated_expr => {}
-                        ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {}
-                        _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span),
-                    }
-
                     let token_kind = token::Interpolated(Lrc::new(token::NtExpr(expr)));
                     MacArgs::Eq(eq_span, Token::new(token_kind, span))
                 } else {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index d537741c749..89cf2d7876e 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -226,6 +226,19 @@ impl<'a> Parser<'a> {
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
+        } else if self.token.is_keyword(kw::Union)
+            && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
+        {
+            self.bump();
+            let (fields, recovered) = self.parse_record_struct_body("union")?;
+            let span = lo.to(self.prev_token.span);
+            self.sess.gated_spans.gate(sym::unnamed_fields, span);
+            TyKind::AnonymousUnion(fields, recovered)
+        } else if self.eat_keyword(kw::Struct) {
+            let (fields, recovered) = self.parse_record_struct_body("struct")?;
+            let span = lo.to(self.prev_token.span);
+            self.sess.gated_spans.gate(sym::unnamed_fields, span);
+            TyKind::AnonymousStruct(fields, recovered)
         } else if self.is_explicit_dyn_type() {
             self.parse_dyn_ty(&mut impl_dyn_multi)?
         } else if self.eat_lt() {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d32180525bf..bef56bbc287 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -5,7 +5,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{Node, PatKind, TyKind};
@@ -44,6 +44,7 @@ struct MarkSymbolVisitor<'tcx> {
     repr_has_repr_c: bool,
     in_pat: bool,
     inherited_pub_visibility: bool,
+    pub_visibility: bool,
     ignore_variant_stack: Vec<DefId>,
     // maps from tuple struct constructors to tuple struct items
     struct_constructors: FxHashMap<hir::HirId, hir::HirId>,
@@ -188,27 +189,33 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
 
     fn visit_node(&mut self, node: Node<'tcx>) {
         let had_repr_c = self.repr_has_repr_c;
-        self.repr_has_repr_c = false;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
+        let had_pub_visibility = self.pub_visibility;
+        self.repr_has_repr_c = false;
         self.inherited_pub_visibility = false;
+        self.pub_visibility = false;
         match node {
-            Node::Item(item) => match item.kind {
-                hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
-                    let def = self.tcx.adt_def(item.def_id);
-                    self.repr_has_repr_c = def.repr.c();
+            Node::Item(item) => {
+                self.pub_visibility = item.vis.node.is_pub();
 
-                    intravisit::walk_item(self, &item);
-                }
-                hir::ItemKind::Enum(..) => {
-                    self.inherited_pub_visibility = item.vis.node.is_pub();
+                match item.kind {
+                    hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
+                        let def = self.tcx.adt_def(item.def_id);
+                        self.repr_has_repr_c = def.repr.c();
 
-                    intravisit::walk_item(self, &item);
-                }
-                hir::ItemKind::ForeignMod { .. } => {}
-                _ => {
-                    intravisit::walk_item(self, &item);
+                        intravisit::walk_item(self, &item);
+                    }
+                    hir::ItemKind::Enum(..) => {
+                        self.inherited_pub_visibility = self.pub_visibility;
+
+                        intravisit::walk_item(self, &item);
+                    }
+                    hir::ItemKind::ForeignMod { .. } => {}
+                    _ => {
+                        intravisit::walk_item(self, &item);
+                    }
                 }
-            },
+            }
             Node::TraitItem(trait_item) => {
                 intravisit::walk_trait_item(self, trait_item);
             }
@@ -220,8 +227,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
             _ => {}
         }
-        self.repr_has_repr_c = had_repr_c;
+        self.pub_visibility = had_pub_visibility;
         self.inherited_pub_visibility = had_inherited_pub_visibility;
+        self.repr_has_repr_c = had_repr_c;
     }
 
     fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::ExprField<'_>]) {
@@ -259,10 +267,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     ) {
         let has_repr_c = self.repr_has_repr_c;
         let inherited_pub_visibility = self.inherited_pub_visibility;
-        let live_fields = def
-            .fields()
-            .iter()
-            .filter(|f| has_repr_c || inherited_pub_visibility || f.vis.node.is_pub());
+        let pub_visibility = self.pub_visibility;
+        let live_fields = def.fields().iter().filter(|f| {
+            has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub()))
+        });
         self.live_symbols.extend(live_fields.map(|f| f.hir_id));
 
         intravisit::walk_struct_def(self, def);
@@ -472,7 +480,7 @@ fn create_and_seed_worklist<'tcx>(
         )
         .chain(
             // Seed entry point
-            tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| {
+            tcx.entry_fn(()).and_then(|(def_id, _)| {
                 def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }),
         )
@@ -500,6 +508,7 @@ fn find_live<'tcx>(
         repr_has_repr_c: false,
         in_pat: false,
         inherited_pub_visibility: false,
+        pub_visibility: false,
         ignore_variant_stack: vec![],
         struct_constructors,
     };
@@ -708,7 +717,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
 }
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
-    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
+    let access_levels = &tcx.privacy_access_levels(());
     let krate = tcx.hir().krate();
     let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor { tcx, live_symbols };
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 8dd3700e5b6..f345d45d178 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, LocalDefId, LOCAL_CRATE};
+use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
 
 struct DiagnosticItemCollector<'tcx> {
@@ -99,7 +99,9 @@ fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> {
 }
 
 /// Traverse and collect the diagnostic items in the current
-fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
+fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap<Symbol, DefId> {
+    assert_eq!(cnum, LOCAL_CRATE);
+
     // Initialize the collector.
     let mut collector = DiagnosticItemCollector::new(tcx);
 
@@ -114,7 +116,7 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
 }
 
 /// Traverse and collect all the diagnostic items in all crates.
-fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
+fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap<Symbol, DefId> {
     // Initialize the collector.
     let mut collector = FxHashMap::default();
 
@@ -129,12 +131,6 @@ fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.diagnostic_items = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        collect(tcx)
-    };
-    providers.all_diagnostic_items = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        collect_all(tcx)
-    };
+    providers.diagnostic_items = diagnostic_items;
+    providers.all_diagnostic_items = all_diagnostic_items;
 }
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 65cfe986ad4..ca6a7561f3e 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,6 +1,6 @@
 use rustc_ast::entry::EntryPointType;
 use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID};
 use rustc_middle::hir::map::Map;
@@ -48,9 +48,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
     }
 }
 
-fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
-    assert_eq!(cnum, LOCAL_CRATE);
-
+fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
     if !any_exe {
         // No need to find a main function.
@@ -227,10 +225,6 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
     err.emit();
 }
 
-pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> {
-    tcx.entry_fn(LOCAL_CRATE)
-}
-
 pub fn provide(providers: &mut Providers) {
     *providers = Providers { entry_fn, ..*providers };
 }
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs
index 4532a0a350c..012d97ef106 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_passes/src/intrinsicck.rs
@@ -347,7 +347,7 @@ impl ExprVisitor<'tcx> {
     }
 
     fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
-        for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
+        for (idx, (op, _)) in asm.operands.iter().enumerate() {
             match *op {
                 hir::InlineAsmOperand::In { reg, ref expr } => {
                     self.check_asm_operand_type(idx, reg, expr, asm.template, None);
@@ -372,19 +372,7 @@ impl ExprVisitor<'tcx> {
                         );
                     }
                 }
-                hir::InlineAsmOperand::Const { ref anon_const } => {
-                    let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                    let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
-                    match value.ty.kind() {
-                        ty::Int(_) | ty::Uint(_) | ty::Float(_) => {}
-                        _ => {
-                            let msg =
-                                "asm `const` arguments must be integer or floating-point values";
-                            self.tcx.sess.span_err(*op_sp, msg);
-                        }
-                    }
-                }
-                hir::InlineAsmOperand::Sym { .. } => {}
+                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {}
             }
         }
     }
@@ -405,33 +393,6 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> {
         ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body);
         self.visit_body(body);
     }
-
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let hir::ItemKind::GlobalAsm(asm) = item.kind {
-            for (op, op_sp) in asm.operands {
-                match *op {
-                    hir::InlineAsmOperand::Const { ref anon_const } => {
-                        let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                        let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
-                        match value.ty.kind() {
-                            ty::Int(_) | ty::Uint(_) | ty::Float(_) => {}
-                            _ => {
-                                let msg = "asm `const` arguments must be integer or floating-point values";
-                                self.tcx.sess.span_err(*op_sp, msg);
-                            }
-                        }
-                    }
-                    hir::InlineAsmOperand::In { .. }
-                    | hir::InlineAsmOperand::Out { .. }
-                    | hir::InlineAsmOperand::InOut { .. }
-                    | hir::InlineAsmOperand::SplitInOut { .. }
-                    | hir::InlineAsmOperand::Sym { .. } => unreachable!(),
-                }
-            }
-        }
-
-        intravisit::walk_item(self, item);
-    }
 }
 
 impl Visitor<'tcx> for ExprVisitor<'tcx> {
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 7e6bb9779f0..118fcca4508 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -13,12 +13,13 @@ use crate::weak_lang_items;
 use rustc_middle::middle::cstore::ExternCrate;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_errors::struct_span_err;
+use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::lang_items::{extract, ITEM_REFS};
 use rustc_hir::{HirId, LangItem, LanguageItems, Target};
+use rustc_span::Span;
 
 use rustc_middle::ty::query::Providers;
 
@@ -61,8 +62,7 @@ impl LanguageItemCollector<'tcx> {
             match ITEM_REFS.get(&value).cloned() {
                 // Known lang item with attribute on correct target.
                 Some((item_index, expected_target)) if actual_target == expected_target => {
-                    let def_id = self.tcx.hir().local_def_id(hir_id);
-                    self.collect_item(item_index, def_id.to_def_id());
+                    self.collect_item_extended(item_index, hir_id, span);
                 }
                 // Known lang item with attribute on incorrect target.
                 Some((_, expected_target)) => {
@@ -180,10 +180,131 @@ impl LanguageItemCollector<'tcx> {
             self.items.groups[group as usize].push(item_def_id);
         }
     }
+
+    // Like collect_item() above, but also checks whether the lang item is declared
+    // with the right number of generic arguments if it is a trait.
+    fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
+        let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+        let lang_item = LangItem::from_u32(item_index as u32).unwrap();
+        let name = lang_item.name();
+
+        self.collect_item(item_index, item_def_id);
+
+        // Now check whether the lang_item has the expected number of generic
+        // arguments if it is a trait. Generally speaking, binary and indexing
+        // operations have one (for the RHS/index), unary operations have none,
+        // and the rest also have none except for the closure traits (one for
+        // the argument list), generators (one for the resume argument),
+        // ordering/equality relations (one for the RHS), and various conversion
+        // traits.
+
+        let expected_num = match lang_item {
+            // Binary operations
+            LangItem::Add
+            | LangItem::Sub
+            | LangItem::Mul
+            | LangItem::Div
+            | LangItem::Rem
+            | LangItem::BitXor
+            | LangItem::BitAnd
+            | LangItem::BitOr
+            | LangItem::Shl
+            | LangItem::Shr
+            | LangItem::AddAssign
+            | LangItem::SubAssign
+            | LangItem::MulAssign
+            | LangItem::DivAssign
+            | LangItem::RemAssign
+            | LangItem::BitXorAssign
+            | LangItem::BitAndAssign
+            | LangItem::BitOrAssign
+            | LangItem::ShlAssign
+            | LangItem::ShrAssign
+            | LangItem::Index
+            | LangItem::IndexMut
+
+            // Miscellaneous
+            | LangItem::Unsize
+            | LangItem::CoerceUnsized
+            | LangItem::DispatchFromDyn
+            | LangItem::Fn
+            | LangItem::FnMut
+            | LangItem::FnOnce
+            | LangItem::Generator
+            | LangItem::PartialEq
+            | LangItem::PartialOrd
+                => Some(1),
+
+            // Unary operations
+            LangItem::Neg
+            | LangItem::Not
+
+            // Miscellaneous
+            | LangItem::Deref
+            | LangItem::DerefMut
+            | LangItem::Sized
+            | LangItem::StructuralPeq
+            | LangItem::StructuralTeq
+            | LangItem::Copy
+            | LangItem::Clone
+            | LangItem::Sync
+            | LangItem::DiscriminantKind
+            | LangItem::PointeeTrait
+            | LangItem::Freeze
+            | LangItem::Drop
+            | LangItem::Receiver
+            | LangItem::Future
+            | LangItem::Unpin
+            | LangItem::Termination
+            | LangItem::Try
+            | LangItem::Send
+            | LangItem::UnwindSafe
+            | LangItem::RefUnwindSafe
+                => Some(0),
+
+            // Not a trait
+            _ => None,
+        };
+
+        if let Some(expected_num) = expected_num {
+            let (actual_num, generics_span) = match self.tcx.hir().get(hir_id) {
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, ..),
+                    ..
+                }) => (generics.params.len(), generics.span),
+                _ => bug!("op/index/deref lang item target is not a trait: {:?}", lang_item),
+            };
+
+            if expected_num != actual_num {
+                // We are issuing E0718 "incorrect target" here, because while the
+                // item kind of the target is correct, the target is still wrong
+                // because of the wrong number of generic arguments.
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0718,
+                    "`{}` language item must be applied to a trait with {} generic argument{}",
+                    name,
+                    expected_num,
+                    pluralize!(expected_num)
+                )
+                .span_label(
+                    generics_span,
+                    format!(
+                        "this trait has {} generic argument{}, not {}",
+                        actual_num,
+                        pluralize!(actual_num),
+                        expected_num
+                    ),
+                )
+                .emit();
+            }
+        }
+    }
 }
 
 /// Traverses and collects all the lang items in all crates.
-fn collect(tcx: TyCtxt<'_>) -> LanguageItems {
+fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
     // Initialize the collector.
     let mut collector = LanguageItemCollector::new(tcx);
 
@@ -207,8 +328,5 @@ fn collect(tcx: TyCtxt<'_>) -> LanguageItems {
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.get_lang_items = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        collect(tcx)
-    };
+    providers.get_lang_items = get_lang_items;
 }
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 3dfe317a4bd..363a6417f99 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -6,7 +6,6 @@
 
 use rustc_ast::{Attribute, MetaItem, MetaItemKind};
 use rustc_errors::struct_span_err;
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::lib_features::LibFeatures;
@@ -127,7 +126,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
     }
 }
 
-fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
+fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     let krate = tcx.hir().krate();
     for attr in krate.non_exported_macro_attrs {
@@ -138,8 +137,5 @@ fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
 }
 
 pub fn provide(providers: &mut Providers) {
-    providers.get_lib_features = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        collect(tcx)
-    };
+    providers.get_lib_features = get_lib_features;
 }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 20aaaea5b98..0b3227abb5f 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -8,8 +8,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Node;
@@ -250,7 +249,7 @@ impl<'tcx> ReachableContext<'tcx> {
                     // Reachable constants will be inlined into other crates
                     // unconditionally, so we need to make sure that their
                     // contents are also reachable.
-                    hir::ItemKind::Const(_, init) => {
+                    hir::ItemKind::Const(_, init) | hir::ItemKind::Static(_, _, init) => {
                         self.visit_nested_body(init);
                     }
 
@@ -261,7 +260,6 @@ impl<'tcx> ReachableContext<'tcx> {
                     | hir::ItemKind::Use(..)
                     | hir::ItemKind::OpaqueTy(..)
                     | hir::ItemKind::TyAlias(..)
-                    | hir::ItemKind::Static(..)
                     | hir::ItemKind::Mod(..)
                     | hir::ItemKind::ForeignMod { .. }
                     | hir::ItemKind::Impl { .. }
@@ -386,10 +384,8 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
     }
 }
 
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> {
-    debug_assert!(crate_num == LOCAL_CRATE);
-
-    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
+fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
+    let access_levels = &tcx.privacy_access_levels(());
 
     let any_library =
         tcx.sess.crate_types().iter().any(|ty| {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 6b1813fba76..f41e0e03706 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -629,7 +629,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
     // stable (assuming they have not inherited instability from their parent).
 }
 
-fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
+fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
     let is_staged_api =
         tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api;
     let mut staged_api = FxHashMap::default();
@@ -704,11 +704,7 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_unstable_api_usage, ..*providers };
-    providers.stability_index = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        new_index(tcx)
-    };
+    *providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers };
 }
 
 struct Checker<'tcx> {
@@ -880,7 +876,7 @@ impl Visitor<'tcx> for CheckTraitImplStable<'tcx> {
 /// were expected to be library features), and the list of features used from
 /// libraries, identify activated features that don't exist and error about them.
 pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
-    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
+    let access_levels = &tcx.privacy_access_levels(());
 
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs
index a49afa35e46..b95c4a72019 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, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -31,33 +31,25 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> {
 }
 
 /// Finds the function marked with `#[plugin_registrar]`, if any.
-pub fn find_plugin_registrar(tcx: TyCtxt<'_>) -> Option<DefId> {
-    tcx.plugin_registrar_fn(LOCAL_CRATE)
-}
-
-fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
-    assert_eq!(cnum, LOCAL_CRATE);
-
+fn plugin_registrar_fn(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut finder = RegistrarFinder { tcx, registrars: Vec::new() };
     tcx.hir().krate().visit_all_item_likes(&mut finder);
 
-    match finder.registrars.len() {
-        0 => None,
-        1 => {
-            let (def_id, _) = finder.registrars.pop().unwrap();
-            Some(def_id.to_def_id())
-        }
-        _ => {
-            let diagnostic = tcx.sess.diagnostic();
-            let mut e = diagnostic.struct_err("multiple plugin registration functions found");
-            for &(_, span) in &finder.registrars {
-                e.span_note(span, "one is here");
-            }
-            e.emit();
-            diagnostic.abort_if_errors();
-            unreachable!();
+    let (def_id, span) = finder.registrars.pop()?;
+
+    if !finder.registrars.is_empty() {
+        let diagnostic = tcx.sess.diagnostic();
+        let mut e = diagnostic.struct_err("multiple plugin registration functions found");
+        e.span_note(span, "one is here");
+        for &(_, span) in &finder.registrars {
+            e.span_note(span, "one is here");
         }
+        e.emit();
+        diagnostic.abort_if_errors();
+        unreachable!();
     }
+
+    Some(def_id)
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index d37a5be2fe5..1342762bb07 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
 use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
 use rustc_middle::bug;
@@ -2092,9 +2092,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     intravisit::walk_mod(&mut visitor, module, hir_id);
 }
 
-fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels {
-    assert_eq!(krate, LOCAL_CRATE);
-
+fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
     // Build up a set of all exported items in the AST. This is a set of all
     // items which are reachable from external crates based on visibility.
     let mut visitor = EmbargoVisitor {
@@ -2117,10 +2115,8 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels {
     tcx.arena.alloc(visitor.access_levels)
 }
 
-fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) {
-    assert_eq!(krate, LOCAL_CRATE);
-
-    let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
+fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
+    let access_levels = tcx.privacy_access_levels(());
 
     let krate = tcx.hir().krate();
 
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs
index 1fdb37398f9..27a0dc47682 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_query_impl/src/keys.rs
@@ -21,6 +21,16 @@ pub trait Key {
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span;
 }
 
+impl Key for () {
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+
+    fn default_span(&self, _: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx> Key for ty::InstanceDef<'tcx> {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index bcd125ae01d..6c308ad89db 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> {
         let sess = &self.tcx.sess;
         // Save-analysis is emitted per whole session, not per each crate type
         let crate_type = sess.crate_types()[0];
-        let outputs = &*self.tcx.output_filenames(LOCAL_CRATE);
+        let outputs = &*self.tcx.output_filenames(());
 
         if outputs.outputs.contains_key(&OutputType::Metadata) {
             filename_for_metadata(sess, crate_name, outputs)
@@ -1000,7 +1000,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
             // Privacy checking requires and is done after type checking; use a
             // fallback in case the access levels couldn't have been correctly computed.
             let access_levels = match tcx.sess.compile_status() {
-                Ok(..) => tcx.privacy_access_levels(LOCAL_CRATE),
+                Ok(..) => tcx.privacy_access_levels(()),
                 Err(..) => tcx.arena.alloc(AccessLevels::default()),
             };
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0b3dece09ae..14ee083ecee 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -130,10 +130,12 @@ symbols! {
         BTreeSet,
         BinaryHeap,
         Borrow,
+        Break,
         C,
         CString,
         Center,
         Clone,
+        Continue,
         Copy,
         Count,
         Debug,
@@ -326,6 +328,7 @@ symbols! {
         box_patterns,
         box_syntax,
         braced_empty_structs,
+        branch,
         breakpoint,
         bridge,
         bswap,
@@ -374,6 +377,7 @@ symbols! {
         conservative_impl_trait,
         console,
         const_allocate,
+        const_async_blocks,
         const_compare_raw_pointers,
         const_constructor,
         const_eval_limit,
@@ -410,6 +414,7 @@ symbols! {
         constructor,
         contents,
         context,
+        control_flow_enum,
         convert,
         copy,
         copy_closures,
@@ -510,7 +515,6 @@ symbols! {
         env,
         eq,
         ermsb_target_feature,
-        err,
         exact_div,
         except,
         exchange_malloc,
@@ -580,10 +584,10 @@ symbols! {
         frem_fast,
         from,
         from_desugaring,
-        from_error,
         from_generator,
         from_method,
-        from_ok,
+        from_output,
+        from_residual,
         from_size_align_unchecked,
         from_trait,
         from_usize,
@@ -652,7 +656,6 @@ symbols! {
         instruction_set,
         intel,
         into_iter,
-        into_result,
         into_trait,
         intra_doc_pointers,
         intrinsics,
@@ -964,6 +967,7 @@ symbols! {
         repr_packed,
         repr_simd,
         repr_transparent,
+        residual,
         result,
         result_type,
         rhs,
@@ -1015,6 +1019,7 @@ symbols! {
         rustc_expected_cgu_reuse,
         rustc_if_this_changed,
         rustc_inherit_overflow_checks,
+        rustc_insignificant_dtor,
         rustc_layout,
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
@@ -1230,7 +1235,7 @@ symbols! {
         try_blocks,
         try_from_trait,
         try_into_trait,
-        try_trait,
+        try_trait_v2,
         tt,
         tuple,
         tuple_from_req,
@@ -1268,6 +1273,7 @@ symbols! {
         unix,
         unlikely,
         unmarked_api,
+        unnamed_fields,
         unpin,
         unreachable,
         unreachable_code,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c050bbc9b9d..7fb24ad1ed8 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -165,11 +165,11 @@ fn compute_symbol_name(
 
     // FIXME(eddyb) Precompute a custom symbol name based on attributes.
     let is_foreign = if let Some(def_id) = def_id.as_local() {
-        if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id.to_def_id()) {
+        if tcx.plugin_registrar_fn(()) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
-        if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id.to_def_id()) {
+        if tcx.proc_macro_decls_static(()) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 37a834043f6..a70b374fc6d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -485,9 +485,39 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
         mut self,
         predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
     ) -> Result<Self::DynExistential, Self::Error> {
-        for predicate in predicates {
-            self = self.in_binder(&predicate, |mut cx, predicate| {
-                match predicate {
+        // Okay, so this is a bit tricky. Imagine we have a trait object like
+        // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the
+        // output looks really close to the syntax, where the `Bar = &'a ()` bit
+        // is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we
+        // actually desugar these into two separate `ExistentialPredicate`s. We
+        // can't enter/exit the "binder scope" twice though, because then we
+        // would mangle the binders twice. (Also, side note, we merging these
+        // two is kind of difficult, because of potential HRTBs in the Projection
+        // predicate.)
+        //
+        // Also worth mentioning: imagine that we instead had
+        // `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is
+        // under the same binders as `Foo`. Currently, this doesn't matter,
+        // because only *auto traits* are allowed other than the principal trait
+        // and all auto traits don't have any generics. Two things could
+        // make this not an "okay" mangling:
+        // 1) Instead of mangling only *used*
+        // bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a
+        // valid trait predicate);
+        // 2) We allow multiple "principal" traits in the future, or at least
+        // allow in any form another trait predicate that can take generics.
+        //
+        // Here we assume that predicates have the following structure:
+        // [<Trait> [{<Projection>}]] [{<Auto>}]
+        // Since any predicates after the first one shouldn't change the binders,
+        // just put them all in the binders of the first.
+        self = self.in_binder(&predicates[0], |mut cx, _| {
+            for predicate in predicates.iter() {
+                // It would be nice to be able to validate bound vars here, but
+                // projections can actually include bound vars from super traits
+                // because of HRTBs (only in the `Self` type). Also, auto traits
+                // could have different bound vars *anyways*.
+                match predicate.as_ref().skip_binder() {
                     ty::ExistentialPredicate::Trait(trait_ref) => {
                         // Use a type that can't appear in defaults of type parameters.
                         let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0));
@@ -504,9 +534,10 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
                         cx = cx.print_def_path(*def_id, &[])?;
                     }
                 }
-                Ok(cx)
-            })?;
-        }
+            }
+            Ok(cx)
+        })?;
+
         self.push("E");
         Ok(self)
     }
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index f12debb5a34..c17c2961434 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -6,7 +6,6 @@ use rustc_span::Symbol;
 use std::fmt;
 use std::str::FromStr;
 
-#[macro_use]
 macro_rules! def_reg_class {
     ($arch:ident $arch_regclass:ident {
         $(
@@ -51,7 +50,6 @@ macro_rules! def_reg_class {
     }
 }
 
-#[macro_use]
 macro_rules! def_regs {
     ($arch:ident $arch_reg:ident $arch_regclass:ident {
         $(
@@ -129,7 +127,6 @@ macro_rules! def_regs {
     }
 }
 
-#[macro_use]
 macro_rules! types {
     (
         $(_ : $($ty:expr),+;)?
@@ -184,6 +181,7 @@ pub enum InlineAsmArch {
     Mips,
     Mips64,
     PowerPC,
+    PowerPC64,
     SpirV,
     Wasm32,
 }
@@ -201,6 +199,7 @@ impl FromStr for InlineAsmArch {
             "riscv64" => Ok(Self::RiscV64),
             "nvptx64" => Ok(Self::Nvptx64),
             "powerpc" => Ok(Self::PowerPC),
+            "powerpc64" => Ok(Self::PowerPC64),
             "hexagon" => Ok(Self::Hexagon),
             "mips" => Ok(Self::Mips),
             "mips64" => Ok(Self::Mips64),
@@ -290,7 +289,7 @@ impl InlineAsmReg {
             InlineAsmArch::Nvptx64 => {
                 Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
-            InlineAsmArch::PowerPC => {
+            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
                 Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
             InlineAsmArch::Hexagon => {
@@ -485,7 +484,9 @@ impl InlineAsmRegClass {
                 Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
             }
             InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::PowerPC => Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
+                Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
+            }
             InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
                 Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
@@ -653,7 +654,7 @@ pub fn allocatable_registers(
             nvptx::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
-        InlineAsmArch::PowerPC => {
+        InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
             let mut map = powerpc::regclass_map();
             powerpc::fill_reg_map(arch, has_feature, target, &mut map);
             map
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index b254e5f3aaa..42fc25c4ff5 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -33,10 +33,16 @@ impl PowerPCInlineAsmRegClass {
 
     pub fn supported_types(
         self,
-        _arch: InlineAsmArch,
+        arch: InlineAsmArch,
     ) -> &'static [(InlineAsmType, Option<&'static str>)] {
         match self {
-            Self::reg | Self::reg_nonzero => types! { _: I8, I16, I32; },
+            Self::reg | Self::reg_nonzero => {
+                if arch == InlineAsmArch::PowerPC {
+                    types! { _: I8, I16, I32; }
+                } else {
+                    types! { _: I8, I16, I32, I64; }
+                }
+            }
             Self::freg => types! { _: F32, F64; },
         }
     }
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index 35a52896f6f..5808391ee06 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -66,6 +66,7 @@ pub fn opts() -> TargetOptions {
         // FIXME(#13846) this should be enabled for windows
         function_sections: false,
         linker: Some("gcc".to_string()),
+        linker_is_gnu: true,
         dynamic_linking: true,
         executables: true,
         dll_prefix: String::new(),
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index fb4a8ce687c..7e67bc118ec 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -46,6 +46,7 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// type Foo = impl Baz;
     /// fn bar() -> Foo {
     /// //          ^^^ This is the span we are looking for!
+    /// }
     /// ```
     ///
     /// In cases where the fn returns `(impl Trait, impl Trait)` or
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index da5a1af7f77..db396356d67 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -14,7 +14,7 @@ use crate::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
 use rustc_middle::mir::abstract_const::NotConstEvaluatable;
@@ -1427,7 +1427,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some)
         };
         let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let all_traits = self.tcx.all_traits(());
         let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
             .iter()
             .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 6a4d41ffc1a..8bbd2da5375 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -686,17 +686,36 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             return false;
         }
 
+        // Blacklist traits for which it would be nonsensical to suggest borrowing.
+        // For instance, immutable references are always Copy, so suggesting to
+        // borrow would always succeed, but it's probably not what the user wanted.
+        let blacklist: Vec<_> =
+            [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized, LangItem::Send]
+                .iter()
+                .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
+                .collect();
+
         let span = obligation.cause.span;
         let param_env = obligation.param_env;
         let trait_ref = trait_ref.skip_binder();
 
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+        let found_ty = trait_ref.self_ty();
+        let found_ty_str = found_ty.to_string();
+        let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty);
+        let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]);
+        let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty);
+        let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);
+
+        // Try to apply the original trait binding obligation by borrowing.
+        let mut try_borrowing = |new_trait_ref: ty::TraitRef<'tcx>,
+                                 expected_trait_ref: ty::TraitRef<'tcx>,
+                                 mtbl: bool,
+                                 blacklist: &[DefId]|
+         -> bool {
+            if blacklist.contains(&expected_trait_ref.def_id) {
+                return false;
+            }
+
             let new_obligation = Obligation::new(
                 ObligationCause::dummy(),
                 param_env,
@@ -713,8 +732,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
                     let msg = format!(
                         "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                        found_ty_str,
+                        expected_trait_ref.print_only_trait_path(),
                     );
                     if has_custom_message {
                         err.note(&msg);
@@ -730,7 +749,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         span,
                         &format!(
                             "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                            expected_trait_ref.print_only_trait_path(),
                         ),
                     );
 
@@ -745,16 +764,52 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
                         err.span_suggestion(
                             span,
-                            "consider borrowing here",
-                            format!("&{}", snippet),
+                            &format!(
+                                "consider{} borrowing here",
+                                if mtbl { " mutably" } else { "" }
+                            ),
+                            format!("&{}{}", if mtbl { "mut " } else { "" }, snippet),
                             Applicability::MaybeIncorrect,
                         );
                     }
                     return true;
                 }
             }
+            return false;
+        };
+
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+            let expected_trait_ref = obligation.parent_trait_ref.skip_binder();
+            let new_imm_trait_ref =
+                ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
+            let new_mut_trait_ref =
+                ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs);
+            if try_borrowing(new_imm_trait_ref, expected_trait_ref, false, &[]) {
+                return true;
+            } else {
+                return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]);
+            }
+        } else if let ObligationCauseCode::BindingObligation(_, _)
+        | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code
+        {
+            if try_borrowing(
+                ty::TraitRef::new(trait_ref.def_id, imm_substs),
+                trait_ref,
+                false,
+                &blacklist[..],
+            ) {
+                return true;
+            } else {
+                return try_borrowing(
+                    ty::TraitRef::new(trait_ref.def_id, mut_substs),
+                    trait_ref,
+                    true,
+                    &blacklist[..],
+                );
+            }
+        } else {
+            false
         }
-        false
     }
 
     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 64f82817d39..bc8f10e15db 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::Limit;
-use rustc_span::DUMMY_SP;
+use rustc_span::{sym, DUMMY_SP};
 
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
 
@@ -21,6 +21,19 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
     res
 }
 
+fn has_significant_drop_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> bool {
+    let significant_drop_fields =
+        move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter());
+    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
+        .next()
+        .is_some();
+    debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
+    res
+}
+
 struct NeedsDropTypes<'tcx, F> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -155,12 +168,20 @@ where
     }
 }
 
-fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
+// Depending on the implentation of `adt_has_dtor`, it is used to check if the
+// ADT has a destructor or if the ADT only has a significant destructor. For
+// understanding significant destructor look at `adt_significant_drop_tys`.
+fn adt_drop_tys_helper(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    adt_has_dtor: impl Fn(&ty::AdtDef) -> bool,
+) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
     let adt_components = move |adt_def: &ty::AdtDef| {
         if adt_def.is_manually_drop() {
             debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
             return Ok(Vec::new().into_iter());
-        } else if adt_def.destructor(tcx).is_some() {
+        } else if adt_has_dtor(adt_def) {
             debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
             return Err(AlwaysRequiresDrop);
         } else if adt_def.is_union() {
@@ -179,6 +200,30 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw
     res.map(|components| tcx.intern_type_list(&components))
 }
 
+fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+    let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).is_some();
+    adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
+}
+
+fn adt_significant_drop_tys(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
+    let adt_has_dtor = |adt_def: &ty::AdtDef| {
+        adt_def
+            .destructor(tcx)
+            .map(|dtor| !tcx.has_attr(dtor.did, sym::rustc_insignificant_dtor))
+            .unwrap_or(false)
+    };
+    adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
+}
+
 pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { needs_drop_raw, adt_drop_tys, ..*providers };
+    *providers = ty::query::Providers {
+        needs_drop_raw,
+        has_significant_drop_raw,
+        adt_drop_tys,
+        adt_significant_drop_tys,
+        ..*providers
+    };
 }
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 5285c1c8598..ef195621044 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1394,11 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
             ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
         });
+        // N.b. principal, projections, auto traits
+        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
         let mut v = regular_trait_predicates
-            .chain(auto_trait_predicates)
             .chain(
                 existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
             )
+            .chain(auto_trait_predicates)
             .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
         v.dedup();
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index e40aa914858..5f26e701c0a 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -89,19 +89,31 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
             if let Some((unresolved_type, unresolved_type_span)) =
                 self.fcx.unresolved_type_vars(&ty)
             {
-                let note = format!(
-                    "the type is part of the {} because of this {}",
-                    self.kind, yield_data.source
-                );
-
                 // If unresolved type isn't a ty_var then unresolved_type_span is None
                 let span = self
                     .prev_unresolved_span
                     .unwrap_or_else(|| unresolved_type_span.unwrap_or(source_span));
-                self.fcx
-                    .need_type_info_err_in_generator(self.kind, span, unresolved_type)
-                    .span_note(yield_data.span, &*note)
-                    .emit();
+
+                // If we encounter an int/float variable, then inference fallback didn't
+                // finish due to some other error. Don't emit spurious additional errors.
+                if let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) =
+                    unresolved_type.kind()
+                {
+                    self.fcx
+                        .tcx
+                        .sess
+                        .delay_span_bug(span, &format!("Encountered var {:?}", unresolved_type));
+                } else {
+                    let note = format!(
+                        "the type is part of the {} because of this {}",
+                        self.kind, yield_data.source
+                    );
+
+                    self.fcx
+                        .need_type_info_err_in_generator(self.kind, span, unresolved_type)
+                        .span_note(yield_data.span, &*note)
+                        .emit();
+                }
             } else {
                 // Insert the type into the ordered set.
                 let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree));
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index 0b1129a6312..427102afee1 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -303,8 +303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         opt_input_types: Option<&[Ty<'tcx>]>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!(
-            "lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?})",
-            self_ty, m_name, trait_def_id
+            "lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})",
+            self_ty, m_name, trait_def_id, opt_input_types
         );
 
         // Construct a trait-reference `self_ty : Trait<input_tys>`
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index b2e4e7a981d..2320a29e6d8 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
@@ -1440,11 +1440,11 @@ impl Ord for TraitInfo {
 
 /// Retrieves all traits in this crate and any dependent crates.
 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
-    tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
+    tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
 }
 
 /// Computes all traits in this crate and any dependent crates.
-fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
+fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
     use hir::itemlikevisit;
 
     let mut traits = vec![];
@@ -1503,14 +1503,11 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
         handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
     }
 
-    traits
+    tcx.arena.alloc_from_iter(traits)
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    providers.all_traits = |tcx, cnum| {
-        assert_eq!(cnum, LOCAL_CRATE);
-        &tcx.arena.alloc(compute_all_traits(tcx))[..]
-    }
+    providers.all_traits = compute_all_traits;
 }
 
 struct UsePlacementFinder<'tcx> {
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 994206bd419..ad7853b7cd0 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -105,7 +105,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
@@ -554,10 +554,8 @@ fn typeck_with_fallback<'tcx>(
                                 _ => false,
                             }) =>
                         {
-                            fcx.next_ty_var(TypeVariableOrigin {
-                                kind: TypeVariableOriginKind::MiscVariable,
-                                span,
-                            })
+                            // Inline assembly constants must be integers.
+                            fcx.next_int_var()
                         }
                         _ => fallback(),
                     },
@@ -1162,8 +1160,7 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
     fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
 
-fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) {
-    debug_assert!(crate_num == LOCAL_CRATE);
+fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
     tcx.par_body_owners(|body_owner_def_id| {
         tcx.ensure().typeck(body_owner_def_id);
     });
@@ -1190,3 +1187,14 @@ fn fatally_break_rust(sess: &Session) {
 fn potentially_plural_count(count: usize, word: &str) -> String {
     format!("{} {}{}", count, word, pluralize!(count))
 }
+
+fn has_expected_num_generic_args<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_did: Option<DefId>,
+    expected: usize,
+) -> bool {
+    trait_did.map_or(true, |trait_did| {
+        let generics = tcx.generics_of(trait_did);
+        generics.count() == expected + if generics.has_self { 1 } else { 0 }
+    })
+}
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index 567cb1a90d0..963436d05d8 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -1,7 +1,7 @@
 //! Code related to processing overloaded binary and unary operators.
 
 use super::method::MethodCallee;
-use super::FnCtxt;
+use super::{has_expected_num_generic_args, FnCtxt};
 use rustc_ast as ast;
 use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -795,6 +795,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             lhs_ty, op, opname, trait_did
         );
 
+        // Catches cases like #83893, where a lang item is declared with the
+        // wrong number of generic arguments. Should have yielded an error
+        // elsewhere by now, but we have to catch it here so that we do not
+        // index `other_tys` out of bounds (if the lang item has too many
+        // generic arguments, `other_tys` is too short).
+        if !has_expected_num_generic_args(
+            self.tcx,
+            trait_did,
+            match op {
+                // Binary ops have a generic right-hand side, unary ops don't
+                Op::Binary(..) => 1,
+                Op::Unary(..) => 0,
+            },
+        ) {
+            return Err(());
+        }
+
         let method = trait_did.and_then(|trait_did| {
             let opname = Ident::with_dummy_span(opname);
             self.lookup_method_in_trait(span, opname, trait_did, lhs_ty, Some(other_tys))
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs
index 5bd385107ca..a63aec07ad1 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_typeck/src/check/place_op.rs
@@ -1,5 +1,5 @@
 use crate::check::method::MethodCallee;
-use crate::check::{FnCtxt, PlaceOp};
+use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp};
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::InferOk;
@@ -153,6 +153,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref),
             PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index),
         };
+
+        // If the lang item was declared incorrectly, stop here so that we don't
+        // run into an ICE (#83893). The error is reported where the lang item is
+        // declared.
+        if !has_expected_num_generic_args(
+            self.tcx,
+            imm_tr,
+            match op {
+                PlaceOp::Deref => 0,
+                PlaceOp::Index => 1,
+            },
+        ) {
+            return None;
+        }
+
         imm_tr.and_then(|trait_did| {
             self.lookup_method_in_trait(
                 span,
@@ -177,6 +192,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PlaceOp::Deref => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut),
             PlaceOp::Index => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
         };
+
+        // If the lang item was declared incorrectly, stop here so that we don't
+        // run into an ICE (#83893). The error is reported where the lang item is
+        // declared.
+        if !has_expected_num_generic_args(
+            self.tcx,
+            mut_tr,
+            match op {
+                PlaceOp::Deref => 0,
+                PlaceOp::Index => 1,
+            },
+        ) {
+            return None;
+        }
+
         mut_tr.and_then(|trait_did| {
             self.lookup_method_in_trait(
                 span,
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 7a2b5b26ef4..71e222c560a 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -323,7 +323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// InferBorrowKind results in a structure like this:
     ///
-    /// ```
+    /// ```text
     /// {
     ///       Place(base: hir_id_s, projections: [], ....) -> {
     ///                                                            capture_kind_expr: hir_id_L5,
@@ -348,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// ```
     ///
     /// After the min capture analysis, we get:
-    /// ```
+    /// ```text
     /// {
     ///       hir_id_s -> [
     ///            Place(base: hir_id_s, projections: [], ....) -> {
@@ -706,6 +706,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///   enabled, **and**
     /// - It wasn't completely captured by the closure, **and**
     /// - One of the paths starting at this root variable, that is not captured needs Drop.
+    ///
+    /// This function only returns true for significant drops. A type is considerent to have a
+    /// significant drop if it's Drop implementation is not annotated by `rustc_insignificant_dtor`.
     fn compute_2229_migrations_for_drop(
         &self,
         closure_def_id: DefId,
@@ -716,7 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
 
-        if !ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
+        if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
             return false;
         }
 
@@ -835,11 +838,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// using list of `Projection` slices), it returns true if there is a path that is not
     /// captured starting at this root variable that implements Drop.
     ///
-    /// FIXME(project-rfc-2229#35): This should return true only for significant drops.
-    ///                             A drop is significant if it's implemented by the user or does
-    ///                             anything that will have any observable behavior (other than
-    ///                             freeing up memory).
-    ///
     /// The way this function works is at a given call it looks at type `base_path_ty` of some base
     /// path say P and then list of projection slices which represent the different captures moved
     /// into the closure starting off of P.
@@ -895,7 +893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///     (Ty((w.p).x), [ &[] ])     (Ty((w.p).y), []) // IMP 2
     ///          |                             |
     ///          v                             v
-    ///        false                     NeedsDrop(Ty(w.p.y))
+    ///        false              NeedsSignificantDrop(Ty(w.p.y))
     ///                                        |
     ///                                        v
     ///                                      true
@@ -939,7 +937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         captured_by_move_projs: Vec<&[Projection<'tcx>]>,
     ) -> bool {
         let needs_drop = |ty: Ty<'tcx>| {
-            ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local()))
+            ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local()))
         };
 
         let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index e1743a5dfc1..836bed2a156 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint;
@@ -77,7 +77,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
     // can always suggest removing (no matter which edition we are
     // in).
     let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx
-        .maybe_unused_extern_crates(LOCAL_CRATE)
+        .maybe_unused_extern_crates(())
         .iter()
         .filter(|&&(def_id, _)| {
             // The `def_id` here actually was calculated during resolution (at least
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index cc592c7a260..51698437a30 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -9,16 +9,14 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt};
 
 use rustc_span::Span;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
-pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateInherentImpls {
-    assert_eq!(crate_num, LOCAL_CRATE);
-
+pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
     let krate = tcx.hir().krate();
     let mut collect = InherentCollect { tcx, impls_map: Default::default() };
     krate.visit_all_item_likes(&mut collect);
@@ -27,9 +25,9 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateInhere
 
 /// On-demand query: yields a vector of the inherent impls for a specific type.
 pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
-    assert!(ty_def_id.is_local());
+    let ty_def_id = ty_def_id.expect_local();
 
-    let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
+    let crate_map = tcx.crate_inherent_impls(());
     match crate_map.inherent_impls.get(&ty_def_id) {
         Some(v) => &v[..],
         None => &[],
@@ -364,7 +362,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
 
 impl InherentCollect<'tcx> {
     fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) {
-        if def_id.is_local() {
+        if let Some(def_id) = def_id.as_local() {
             // 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.
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
index c69389e7b43..f039790eca1 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Symbol;
@@ -9,8 +9,7 @@ use rustc_trait_selection::traits::{self, SkipLeakCheck};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 
-pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
-    assert_eq!(crate_num, LOCAL_CRATE);
+pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) {
     let krate = tcx.hir().krate();
     krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
 }
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs
index f04782a1f44..03a9fe01795 100644
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ b/compiler/rustc_typeck/src/coherence/mod.rs
@@ -6,7 +6,7 @@
 // mappings. That mapping code resides here.
 
 use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::Span;
@@ -203,8 +203,8 @@ pub fn check_coherence(tcx: TyCtxt<'_>) {
     tcx.sess.time("orphan_checking", || orphan::check(tcx));
 
     // these queries are executed for side-effects (error reporting):
-    tcx.ensure().crate_inherent_impls(LOCAL_CRATE);
-    tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE);
+    tcx.ensure().crate_inherent_impls(());
+    tcx.ensure().crate_inherent_impls_overlap_check(());
 }
 
 /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 4e07e52347a..47299722325 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -97,7 +97,7 @@ mod variance;
 
 use rustc_errors::{struct_span_err, ErrorReported};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_infer::infer::{InferOk, TyCtxtInferExt};
 use rustc_infer::traits::TraitEngineExt as _;
@@ -449,7 +449,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
 }
 
 fn check_for_entry_fn(tcx: TyCtxt<'_>) {
-    match tcx.entry_fn(LOCAL_CRATE) {
+    match tcx.entry_fn(()) {
         Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
         _ => {}
@@ -510,7 +510,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
         }
     });
 
-    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE));
+    tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
 
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs
index e94b8450bfd..d7eb31c2abe 100644
--- a/compiler/rustc_typeck/src/outlives/mod.rs
+++ b/compiler/rustc_typeck/src/outlives/mod.rs
@@ -1,6 +1,6 @@
 use hir::Node;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
@@ -23,7 +23,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate
     match tcx.hir().get(id) {
         Node::Item(item) => match item.kind {
             hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
-                let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
+                let crate_map = tcx.inferred_outlives_crate(());
 
                 let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]);
 
@@ -58,9 +58,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate
     }
 }
 
-fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredicatesMap<'_> {
-    assert_eq!(crate_num, LOCAL_CRATE);
-
+fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
     // Compute a map from each struct/enum/union S to the **explicit**
     // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
     // Typically there won't be many of these, except in older code where
diff --git a/compiler/rustc_typeck/src/variance/mod.rs b/compiler/rustc_typeck/src/variance/mod.rs
index 1565efbb022..66fb9eb8693 100644
--- a/compiler/rustc_typeck/src/variance/mod.rs
+++ b/compiler/rustc_typeck/src/variance/mod.rs
@@ -6,7 +6,7 @@
 use hir::Node;
 use rustc_arena::DroplessArena;
 use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt};
 
@@ -30,8 +30,7 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers { variances_of, crate_variances, ..*providers };
 }
 
-fn crate_variances(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateVariancesMap<'_> {
-    assert_eq!(crate_num, LOCAL_CRATE);
+fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
     let arena = DroplessArena::default();
     let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &arena);
     let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
@@ -79,6 +78,6 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
 
     // Everything else must be inferred.
 
-    let crate_map = tcx.crate_variances(LOCAL_CRATE);
+    let crate_map = tcx.crate_variances(());
     crate_map.variances.get(&item_def_id).copied().unwrap_or(&[])
 }