Rollup merge of #97354 - GuillaumeGomez:browser-ui-test-update, r=notriddle

Updates to browser-ui-test

I took the commits from #97317. Since the ubuntu 22.04 version, you either need to use `--no-sandbox` or use another binary to run the GUI tests. I couldn't find out why the chromium used by `browser-ui-test` isn't working anymore on this ubuntu version.

r? `@notriddle`
diff --git a/Cargo.lock b/Cargo.lock
index 9fa6e1d..7154061 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@
 
 [[package]]
 name = "cargo"
-version = "0.63.0"
+version = "0.64.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -970,9 +970,9 @@
 
 [[package]]
 name = "curl"
-version = "0.4.41"
+version = "0.4.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bc6d233563261f8db6ffb83bbaad5a73837a6e6b28868e926337ebbdece0be3"
+checksum = "37d855aeef205b43f65a5001e0997d81f8efca7badad4fad7d897aa7f0d0651f"
 dependencies = [
  "curl-sys",
  "libc",
@@ -985,9 +985,9 @@
 
 [[package]]
 name = "curl-sys"
-version = "0.4.51+curl-7.80.0"
+version = "0.4.55+curl-7.83.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d130987e6a6a34fe0889e1083022fa48cd90e6709a84be3fb8dd95801de5af20"
+checksum = "23734ec77368ec583c2e61dd3f0b0e5c98b93abe6d2a004ca06b91dd7e3e2762"
 dependencies = [
  "cc",
  "libc",
@@ -2225,12 +2225,6 @@
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
 [[package]]
-name = "macro-utils"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e72f7deb758fea9ea7d290aebfa788763d0bffae12caa6406a25baaf8fa68a8"
-
-[[package]]
 name = "maplit"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2361,12 +2355,9 @@
 
 [[package]]
 name = "minifier"
-version = "0.0.43"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d81352bda6f4d04af1720afaa762054f66e16caffd93c1f86461a1c0ac4e695e"
-dependencies = [
- "macro-utils",
-]
+checksum = "7071d17e2898e134cabf624f43cdefa0cedf57c739e964df3d0df9d028701a72"
 
 [[package]]
 name = "minimal-lexical"
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2704cb8..c8f1e1d 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -454,6 +454,15 @@
     sess.first_attr_value_str_by_name(attrs, sym::crate_name)
 }
 
+#[derive(Clone, Debug)]
+pub struct Condition {
+    pub name: Symbol,
+    pub name_span: Span,
+    pub value: Option<Symbol>,
+    pub value_span: Option<Span>,
+    pub span: Span,
+}
+
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(
     cfg: &ast::MetaItem,
@@ -462,70 +471,42 @@
     features: Option<&Features>,
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
-        try_gate_cfg(cfg, sess, features);
-        let error = |span, msg| {
-            sess.span_diagnostic.span_err(span, msg);
-            true
-        };
-        if cfg.path.segments.len() != 1 {
-            return error(cfg.path.span, "`cfg` predicate key must be an identifier");
-        }
-        match &cfg.kind {
-            MetaItemKind::List(..) => {
-                error(cfg.span, "unexpected parentheses after `cfg` predicate key")
-            }
-            MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                handle_errors(
-                    sess,
-                    lit.span,
-                    AttrError::UnsupportedLiteral(
-                        "literal in `cfg` predicate value must be a string",
-                        lit.kind.is_bytestr(),
-                    ),
+        try_gate_cfg(cfg.name, cfg.span, sess, features);
+        if let Some(names_valid) = &sess.check_config.names_valid {
+            if !names_valid.contains(&cfg.name) {
+                sess.buffer_lint_with_diagnostic(
+                    UNEXPECTED_CFGS,
+                    cfg.span,
+                    lint_node_id,
+                    "unexpected `cfg` condition name",
+                    BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
                 );
-                true
-            }
-            MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                let ident = cfg.ident().expect("multi-segment cfg predicate");
-                let name = ident.name;
-                let value = cfg.value_str();
-                if let Some(names_valid) = &sess.check_config.names_valid {
-                    if !names_valid.contains(&name) {
-                        sess.buffer_lint_with_diagnostic(
-                            UNEXPECTED_CFGS,
-                            cfg.span,
-                            lint_node_id,
-                            "unexpected `cfg` condition name",
-                            BuiltinLintDiagnostics::UnexpectedCfg((name, ident.span), None),
-                        );
-                    }
-                }
-                if let Some(value) = value {
-                    if let Some(values) = &sess.check_config.values_valid.get(&name) {
-                        if !values.contains(&value) {
-                            sess.buffer_lint_with_diagnostic(
-                                UNEXPECTED_CFGS,
-                                cfg.span,
-                                lint_node_id,
-                                "unexpected `cfg` condition value",
-                                BuiltinLintDiagnostics::UnexpectedCfg(
-                                    (name, ident.span),
-                                    Some((value, cfg.name_value_literal_span().unwrap())),
-                                ),
-                            );
-                        }
-                    }
-                }
-                sess.config.contains(&(name, value))
             }
         }
+        if let Some(value) = cfg.value {
+            if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) {
+                if !values.contains(&value) {
+                    sess.buffer_lint_with_diagnostic(
+                        UNEXPECTED_CFGS,
+                        cfg.span,
+                        lint_node_id,
+                        "unexpected `cfg` condition value",
+                        BuiltinLintDiagnostics::UnexpectedCfg(
+                            (cfg.name, cfg.name_span),
+                            cfg.value_span.map(|vs| (value, vs)),
+                        ),
+                    );
+                }
+            }
+        }
+        sess.config.contains(&(cfg.name, cfg.value))
     })
 }
 
-fn try_gate_cfg(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) {
-    let gate = find_gated_cfg(|sym| cfg.has_name(sym));
+fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
+    let gate = find_gated_cfg(|sym| sym == name);
     if let (Some(feats), Some(gated_cfg)) = (features, gate) {
-        gate_cfg(&gated_cfg, cfg.span, sess, feats);
+        gate_cfg(&gated_cfg, span, sess, feats);
     }
 }
 
@@ -563,11 +544,11 @@
     cfg: &ast::MetaItem,
     sess: &ParseSess,
     features: Option<&Features>,
-    eval: &mut impl FnMut(&ast::MetaItem) -> bool,
+    eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
     match cfg.kind {
         ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
-            try_gate_cfg(cfg, sess, features);
+            try_gate_cfg(sym::version, cfg.span, sess, features);
             let (min_version, span) = match &mis[..] {
                 [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
                     (sym, span)
@@ -649,6 +630,25 @@
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
                 }
+                sym::target => {
+                    if let Some(features) = features && !features.cfg_target_compact {
+                        feature_err(
+                            sess,
+                            sym::cfg_target_compact,
+                            cfg.span,
+                            &"compact `cfg(target(..))` is experimental and subject to change"
+                        ).emit();
+                    }
+
+                    mis.iter().fold(true, |res, mi| {
+                        let mut mi = mi.meta_item().unwrap().clone();
+                        if let [seg, ..] = &mut mi.path.segments[..] {
+                            seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
+                        }
+
+                        res & eval_condition(&mi, sess, features, eval)
+                    })
+                }
                 _ => {
                     struct_span_err!(
                         sess.span_diagnostic,
@@ -662,7 +662,32 @@
                 }
             }
         }
-        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => eval(cfg),
+        ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
+            sess.span_diagnostic
+                .span_err(cfg.path.span, "`cfg` predicate key must be an identifier");
+            true
+        }
+        MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+            handle_errors(
+                sess,
+                lit.span,
+                AttrError::UnsupportedLiteral(
+                    "literal in `cfg` predicate value must be a string",
+                    lit.kind.is_bytestr(),
+                ),
+            );
+            true
+        }
+        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
+            let ident = cfg.ident().expect("multi-segment cfg predicate");
+            eval(Condition {
+                name: ident.name,
+                name_span: ident.span,
+                value: cfg.value_str(),
+                value_span: cfg.name_value_literal_span(),
+                span: cfg.span,
+            })
+        }
     }
 }
 
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index c95c1c4..c3f9f0c 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -4,6 +4,7 @@
 //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
 //! to this crate.
 
+#![feature(let_chains)]
 #![feature(let_else)]
 
 #[macro_use]
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 22edee3..e4ffae3 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -140,9 +140,7 @@
         // A `Call` terminator's return value can be a local which has borrows,
         // so we need to record those as `killed` as well.
         if let TerminatorKind::Call { destination, .. } = terminator.kind {
-            if let Some((place, _)) = destination {
-                self.record_killed_borrows_for_place(place, location);
-            }
+            self.record_killed_borrows_for_place(destination, location);
         }
 
         self.super_terminator(terminator, location);
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 84ff33f..da5f567 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2198,10 +2198,10 @@
                 "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
                 target, terminator
             );
-            if let TerminatorKind::Call { destination: Some((place, _)), args, .. } =
+            if let TerminatorKind::Call { destination, target: Some(_), args, .. } =
                 &terminator.kind
             {
-                if let Some(assigned_to) = place.as_local() {
+                if let Some(assigned_to) = destination.as_local() {
                     debug!(
                         "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
                         assigned_to, args
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 6ec6b76..0b6be45 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -705,10 +705,10 @@
                 let terminator = block.terminator();
                 debug!("was_captured_by_trait_object: terminator={:?}", terminator);
 
-                if let TerminatorKind::Call { destination: Some((place, block)), args, .. } =
+                if let TerminatorKind::Call { destination, target: Some(block), args, .. } =
                     &terminator.kind
                 {
-                    if let Some(dest) = place.as_local() {
+                    if let Some(dest) = destination.as_local() {
                         debug!(
                             "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
                             target, dest, args
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 76d240b..0425c53 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -124,6 +124,7 @@
                 ref func,
                 ref args,
                 destination,
+                target: _,
                 cleanup: _,
                 from_hir_call: _,
                 fn_span: _,
@@ -132,9 +133,7 @@
                 for arg in args {
                     self.consume_operand(location, arg);
                 }
-                if let Some((dest, _ /*bb*/)) = destination {
-                    self.mutate_place(location, *dest, Deep);
-                }
+                self.mutate_place(location, *destination, Deep);
             }
             TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
                 self.consume_operand(location, cond);
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index a3e7c95..d3aea1f 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -661,7 +661,8 @@
             TerminatorKind::Call {
                 ref func,
                 ref args,
-                ref destination,
+                destination,
+                target: _,
                 cleanup: _,
                 from_hir_call: _,
                 fn_span: _,
@@ -670,9 +671,7 @@
                 for arg in args {
                     self.consume_operand(loc, (arg, span), flow_state);
                 }
-                if let Some((dest, _ /*bb*/)) = *destination {
-                    self.mutate_place(loc, (dest, span), Deep, flow_state);
-                }
+                self.mutate_place(loc, (destination, span), Deep, flow_state);
             }
             TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 405fd91..34bc87b 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1403,7 +1403,9 @@
                 }
                 // FIXME: check the values
             }
-            TerminatorKind::Call { ref func, ref args, ref destination, from_hir_call, .. } => {
+            TerminatorKind::Call {
+                ref func, ref args, destination, target, from_hir_call, ..
+            } => {
                 self.check_operand(func, term_location);
                 for arg in args {
                     self.check_operand(arg, term_location);
@@ -1424,7 +1426,7 @@
                     sig,
                 );
                 let sig = self.normalize(sig, term_location);
-                self.check_call_dest(body, term, &sig, destination, term_location);
+                self.check_call_dest(body, term, &sig, destination, target, term_location);
 
                 self.prove_predicates(
                     sig.inputs_and_output
@@ -1502,15 +1504,16 @@
         body: &Body<'tcx>,
         term: &Terminator<'tcx>,
         sig: &ty::FnSig<'tcx>,
-        destination: &Option<(Place<'tcx>, BasicBlock)>,
+        destination: Place<'tcx>,
+        target: Option<BasicBlock>,
         term_location: Location,
     ) {
         let tcx = self.tcx();
-        match *destination {
-            Some((ref dest, _target_block)) => {
-                let dest_ty = dest.ty(body, tcx).ty;
+        match target {
+            Some(_) => {
+                let dest_ty = destination.ty(body, tcx).ty;
                 let dest_ty = self.normalize(dest_ty, term_location);
-                let category = match dest.as_local() {
+                let category = match destination.as_local() {
                     Some(RETURN_PLACE) => {
                         if let BorrowCheckContext {
                             universal_regions:
@@ -1659,8 +1662,8 @@
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::Call { ref destination, cleanup, .. } => {
-                if let &Some((_, target)) = destination {
+            TerminatorKind::Call { ref target, cleanup, .. } => {
+                if let &Some(target) = target {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
                 if let Some(cleanup) = cleanup {
diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index cdbb60b..1093167 100644
--- a/compiler/rustc_borrowck/src/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -66,8 +66,8 @@
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         debug!("visit_terminator: terminator={:?}", terminator);
         match &terminator.kind {
-            TerminatorKind::Call { destination: Some((into, _)), .. } => {
-                self.remove_never_initialized_mut_locals(*into);
+            TerminatorKind::Call { destination, .. } => {
+                self.remove_never_initialized_mut_locals(*destination);
             }
             TerminatorKind::DropAndReplace { place, .. } => {
                 self.remove_never_initialized_mut_locals(*place);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 0fd23fd..0832fda 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -257,7 +257,7 @@
     pub type_ident: Ident,
     /// ident of the method
     pub method_ident: Ident,
-    /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)][ptr]` arguments
+    /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)`][ptr] arguments
     ///
     /// [`Self_`]: ty::Ty::Self_
     /// [ptr]: ty::Ty::Ptr
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index b163a42..decb784 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -312,13 +312,14 @@
     source_info: mir::SourceInfo,
     func: &Operand<'tcx>,
     args: &[Operand<'tcx>],
-    mir_dest: Option<(Place<'tcx>, BasicBlock)>,
+    destination: Place<'tcx>,
+    target: Option<BasicBlock>,
 ) {
     let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
     let fn_sig =
         fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
 
-    let destination = mir_dest.map(|(place, bb)| (codegen_place(fx, place), bb));
+    let ret_place = codegen_place(fx, destination);
 
     // Handle special calls like instrinsics and empty drop glue.
     let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
@@ -333,7 +334,8 @@
                 &fx.tcx.symbol_name(instance).name,
                 substs,
                 args,
-                destination,
+                ret_place,
+                target,
             );
             return;
         }
@@ -344,14 +346,15 @@
                     fx,
                     instance,
                     args,
-                    destination,
+                    ret_place,
+                    target,
                     source_info,
                 );
                 return;
             }
             InstanceDef::DropGlue(_, None) => {
                 // empty drop glue - a nop.
-                let (_, dest) = destination.expect("Non terminating drop_in_place_real???");
+                let dest = target.expect("Non terminating drop_in_place_real???");
                 let ret_block = fx.get_block(dest);
                 fx.bcx.ins().jump(ret_block, &[]);
                 return;
@@ -377,7 +380,7 @@
         .unwrap_or(false);
     if is_cold {
         fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
-        if let Some((_place, destination_block)) = destination {
+        if let Some(destination_block) = target {
             fx.bcx.set_cold_block(fx.get_block(destination_block));
         }
     }
@@ -459,7 +462,6 @@
         }
     };
 
-    let ret_place = destination.map(|(place, _)| place);
     self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
         let call_args = return_ptr
             .into_iter()
@@ -511,7 +513,7 @@
         call_inst
     });
 
-    if let Some((_, dest)) = destination {
+    if let Some(dest) = target {
         let ret_block = fx.get_block(dest);
         fx.bcx.ins().jump(ret_block, &[]);
     } else {
diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs
index c1bdba4..ff3bb2d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs
@@ -56,23 +56,22 @@
 pub(super) fn codegen_with_call_return_arg<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     ret_arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
-    ret_place: Option<CPlace<'tcx>>,
+    ret_place: CPlace<'tcx>,
     f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option<Value>) -> Inst,
 ) {
     let (ret_temp_place, return_ptr) = match ret_arg_abi.mode {
         PassMode::Ignore => (None, None),
-        PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => match ret_place {
-            Some(ret_place) if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) => {
+        PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
+            if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) {
                 // This is an optimization to prevent unnecessary copies of the return value when
                 // the return place is already a memory place as opposed to a register.
                 // This match arm can be safely removed.
                 (None, Some(ret_place.to_ptr().get_addr(fx)))
-            }
-            _ => {
+            } else {
                 let place = CPlace::new_stack_slot(fx, ret_arg_abi.layout);
                 (Some(place), Some(place.to_ptr().get_addr(fx)))
             }
-        },
+        }
         PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
             unreachable!("unsized return value")
         }
@@ -84,39 +83,25 @@
     match ret_arg_abi.mode {
         PassMode::Ignore => {}
         PassMode::Direct(_) => {
-            if let Some(ret_place) = ret_place {
-                let ret_val = fx.bcx.inst_results(call_inst)[0];
-                ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_arg_abi.layout));
-            }
+            let ret_val = fx.bcx.inst_results(call_inst)[0];
+            ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_arg_abi.layout));
         }
         PassMode::Pair(_, _) => {
-            if let Some(ret_place) = ret_place {
-                let ret_val_a = fx.bcx.inst_results(call_inst)[0];
-                let ret_val_b = fx.bcx.inst_results(call_inst)[1];
-                ret_place.write_cvalue(
-                    fx,
-                    CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout),
-                );
-            }
+            let ret_val_a = fx.bcx.inst_results(call_inst)[0];
+            let ret_val_b = fx.bcx.inst_results(call_inst)[1];
+            ret_place
+                .write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout));
         }
         PassMode::Cast(cast) => {
-            if let Some(ret_place) = ret_place {
-                let results = fx
-                    .bcx
-                    .inst_results(call_inst)
-                    .iter()
-                    .copied()
-                    .collect::<SmallVec<[Value; 2]>>();
-                let result =
-                    super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
-                ret_place.write_cvalue(fx, result);
-            }
+            let results =
+                fx.bcx.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>();
+            let result =
+                super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
+            ret_place.write_cvalue(fx, result);
         }
         PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
-            if let (Some(ret_place), Some(ret_temp_place)) = (ret_place, ret_temp_place) {
-                // Both ret_place and ret_temp_place must be Some. If ret_place is None, this is
-                // a non-returning call. If ret_temp_place is None, it is not necessary to copy the
-                // return value.
+            if let Some(ret_temp_place) = ret_temp_place {
+                // If ret_temp_place is None, it is not necessary to copy the return value.
                 let ret_temp_value = ret_temp_place.to_cvalue(fx);
                 ret_place.write_cvalue(fx, ret_temp_value);
             }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 65e5812..3fe112d 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -393,6 +393,7 @@
                 func,
                 args,
                 destination,
+                target,
                 fn_span,
                 cleanup: _,
                 from_hir_call: _,
@@ -404,6 +405,7 @@
                         func,
                         args,
                         *destination,
+                        *target,
                     )
                 });
             }
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 57074f0..7d2e3e5 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -542,8 +542,8 @@
                     | TerminatorKind::FalseEdge { .. }
                     | TerminatorKind::FalseUnwind { .. } => unreachable!(),
                     TerminatorKind::InlineAsm { .. } => return None,
-                    TerminatorKind::Call { destination: Some((call_place, _)), .. }
-                        if call_place == place =>
+                    TerminatorKind::Call { destination, target: Some(_), .. }
+                        if destination == place =>
                     {
                         return None;
                     }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 0e4f7ee..77ac465 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -10,10 +10,9 @@
     intrinsic: &str,
     _substs: SubstsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
-    destination: Option<(CPlace<'tcx>, BasicBlock)>,
+    ret: CPlace<'tcx>,
+    target: Option<BasicBlock>,
 ) {
-    let ret = destination.unwrap().0;
-
     intrinsic_match! {
         fx, intrinsic, args,
         _ => {
@@ -126,7 +125,7 @@
         };
     }
 
-    let dest = destination.expect("all llvm intrinsics used by stdlib should return").1;
+    let dest = target.expect("all llvm intrinsics used by stdlib should return");
     let ret_block = fx.get_block(dest);
     fx.bcx.ins().jump(ret_block, &[]);
 }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 29b3f36..6937e65 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -58,6 +58,7 @@
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_target::abi::InitKind;
 
 use crate::prelude::*;
 use cranelift_codegen::ir::AtomicRmwOp;
@@ -217,35 +218,42 @@
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     instance: Instance<'tcx>,
     args: &[mir::Operand<'tcx>],
-    destination: Option<(CPlace<'tcx>, BasicBlock)>,
+    destination: CPlace<'tcx>,
+    target: Option<BasicBlock>,
     source_info: mir::SourceInfo,
 ) {
     let intrinsic = fx.tcx.item_name(instance.def_id());
     let substs = instance.substs;
 
-    let ret = match destination {
-        Some((place, _)) => place,
-        None => {
-            // Insert non returning intrinsics here
-            match intrinsic {
-                sym::abort => {
-                    fx.bcx.ins().trap(TrapCode::User(0));
-                }
-                sym::transmute => {
-                    crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
-                }
-                _ => unimplemented!("unsupported instrinsic {}", intrinsic),
+    let target = if let Some(target) = target {
+        target
+    } else {
+        // Insert non returning intrinsics here
+        match intrinsic {
+            sym::abort => {
+                fx.bcx.ins().trap(TrapCode::User(0));
             }
-            return;
+            sym::transmute => {
+                crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
+            }
+            _ => unimplemented!("unsupported instrinsic {}", intrinsic),
         }
+        return;
     };
 
     if intrinsic.as_str().starts_with("simd_") {
-        self::simd::codegen_simd_intrinsic_call(fx, intrinsic, substs, args, ret, source_info.span);
-        let ret_block = fx.get_block(destination.expect("SIMD intrinsics don't diverge").1);
+        self::simd::codegen_simd_intrinsic_call(
+            fx,
+            intrinsic,
+            substs,
+            args,
+            destination,
+            source_info.span,
+        );
+        let ret_block = fx.get_block(target);
         fx.bcx.ins().jump(ret_block, &[]);
-    } else if codegen_float_intrinsic_call(fx, intrinsic, args, ret) {
-        let ret_block = fx.get_block(destination.expect("Float intrinsics don't diverge").1);
+    } else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) {
+        let ret_block = fx.get_block(target);
         fx.bcx.ins().jump(ret_block, &[]);
     } else {
         codegen_regular_intrinsic_call(
@@ -254,9 +262,9 @@
             intrinsic,
             substs,
             args,
-            ret,
-            source_info,
             destination,
+            Some(target),
+            source_info,
         );
     }
 }
@@ -339,8 +347,8 @@
     substs: SubstsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
+    destination: Option<BasicBlock>,
     source_info: mir::SourceInfo,
-    destination: Option<(CPlace<'tcx>, BasicBlock)>,
 ) {
     let usize_layout = fx.layout_of(fx.tcx.types.usize);
 
@@ -664,7 +672,12 @@
                 return;
             }
 
-            if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true) {
+            if intrinsic == sym::assert_zero_valid
+                && !layout.might_permit_raw_init(
+                    fx,
+                    InitKind::Zero,
+                    fx.tcx.sess.opts.debugging_opts.strict_init_checks) {
+
                 with_no_trimmed_paths!({
                     crate::base::codegen_panic(
                         fx,
@@ -675,7 +688,12 @@
                 return;
             }
 
-            if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false) {
+            if intrinsic == sym::assert_uninit_valid
+                && !layout.might_permit_raw_init(
+                    fx,
+                    InitKind::Uninit,
+                    fx.tcx.sess.opts.debugging_opts.strict_init_checks) {
+
                 with_no_trimmed_paths!({
                     crate::base::codegen_panic(
                         fx,
@@ -761,7 +779,7 @@
                     if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
                         // special case for compiler-builtins to avoid having to patch it
                         crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
-                        let ret_block = fx.get_block(destination.unwrap().1);
+                        let ret_block = fx.get_block(destination.unwrap());
                         fx.bcx.ins().jump(ret_block, &[]);
                         return;
                     } else {
@@ -789,7 +807,7 @@
                     if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
                         // special case for compiler-builtins to avoid having to patch it
                         crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
-                        let ret_block = fx.get_block(destination.unwrap().1);
+                        let ret_block = fx.get_block(destination.unwrap());
                         fx.bcx.ins().jump(ret_block, &[]);
                         return;
                     } else {
@@ -1130,6 +1148,6 @@
         };
     }
 
-    let ret_block = fx.get_block(destination.unwrap().1);
+    let ret_block = fx.get_block(destination.unwrap());
     fx.bcx.ins().jump(ret_block, &[]);
 }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 41f88f1..479328a 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -61,24 +61,6 @@
     Min,
 }
 
-trait EnumClone {
-    fn clone(&self) -> Self;
-}
-
-impl EnumClone for AtomicOrdering {
-    fn clone(&self) -> Self {
-        match *self {
-            AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic,
-            AtomicOrdering::Unordered => AtomicOrdering::Unordered,
-            AtomicOrdering::Monotonic => AtomicOrdering::Monotonic,
-            AtomicOrdering::Acquire => AtomicOrdering::Acquire,
-            AtomicOrdering::Release => AtomicOrdering::Release,
-            AtomicOrdering::AcquireRelease => AtomicOrdering::AcquireRelease,
-            AtomicOrdering::SequentiallyConsistent => AtomicOrdering::SequentiallyConsistent,
-        }
-    }
-}
-
 pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
     pub cx: &'a CodegenCx<'gcc, 'tcx>,
     pub block: Block<'gcc>,
@@ -103,9 +85,9 @@
             match order {
                 // TODO(antoyo): does this make sense?
                 AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
-                _ => order.clone(),
+                _ => order,
             };
-        let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering.clone(), Size::from_bytes(size));
+        let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size));
         let previous_var = func.new_local(None, previous_value.get_type(), "previous_value");
         let return_value = func.new_local(None, previous_value.get_type(), "return_value");
         self.llbb().add_assignment(None, previous_var, previous_value);
@@ -1384,9 +1366,8 @@
 
         let ordering =
             match self {
-                AtomicOrdering::NotAtomic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
                 AtomicOrdering::Unordered => __ATOMIC_RELAXED,
-                AtomicOrdering::Monotonic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
+                AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
                 AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
                 AtomicOrdering::Release => __ATOMIC_RELEASE,
                 AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 37409db..1d9a465 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -381,9 +381,8 @@
 impl AtomicOrdering {
     pub fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
         match ao {
-            rustc_codegen_ssa::common::AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic,
             rustc_codegen_ssa::common::AtomicOrdering::Unordered => AtomicOrdering::Unordered,
-            rustc_codegen_ssa::common::AtomicOrdering::Monotonic => AtomicOrdering::Monotonic,
+            rustc_codegen_ssa::common::AtomicOrdering::Relaxed => AtomicOrdering::Monotonic,
             rustc_codegen_ssa::common::AtomicOrdering::Acquire => AtomicOrdering::Acquire,
             rustc_codegen_ssa::common::AtomicOrdering::Release => AtomicOrdering::Release,
             rustc_codegen_ssa::common::AtomicOrdering::AcquireRelease => {
diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs
index 17071ba..6c29692 100644
--- a/compiler/rustc_codegen_ssa/src/back/command.rs
+++ b/compiler/rustc_codegen_ssa/src/back/command.rs
@@ -105,12 +105,7 @@
             }
             Program::Lld(ref p, flavor) => {
                 let mut c = process::Command::new(p);
-                c.arg("-flavor").arg(match flavor {
-                    LldFlavor::Wasm => "wasm",
-                    LldFlavor::Ld => "gnu",
-                    LldFlavor::Link => "link",
-                    LldFlavor::Ld64 => "darwin",
-                });
+                c.arg("-flavor").arg(flavor.as_str());
                 if let LldFlavor::Wasm = flavor {
                     // LLVM expects host-specific formatting for @file
                     // arguments, but we always generate posix formatted files
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 04ec1e7..00f8585 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2698,37 +2698,20 @@
         if let LinkerFlavor::Gcc = flavor {
             match ld_impl {
                 LdImpl::Lld => {
-                    if sess.target.lld_flavor == LldFlavor::Ld64 {
-                        let tools_path = sess.get_tools_search_paths(false);
-                        let ld64_exe = tools_path
-                            .into_iter()
-                            .map(|p| p.join("gcc-ld"))
-                            .map(|p| {
-                                p.join(if sess.host.is_like_windows { "ld64.exe" } else { "ld64" })
-                            })
-                            .find(|p| p.exists())
-                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld64) not found"));
-                        cmd.cmd().arg({
-                            let mut arg = OsString::from("-fuse-ld=");
-                            arg.push(ld64_exe);
-                            arg
-                        });
-                    } else {
-                        let tools_path = sess.get_tools_search_paths(false);
-                        let lld_path = tools_path
-                            .into_iter()
-                            .map(|p| p.join("gcc-ld"))
-                            .find(|p| {
-                                p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" })
-                                    .exists()
-                            })
-                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
-                        cmd.cmd().arg({
-                            let mut arg = OsString::from("-B");
-                            arg.push(lld_path);
-                            arg
-                        });
-                    }
+                    let tools_path = sess.get_tools_search_paths(false);
+                    let gcc_ld_dir = tools_path
+                        .into_iter()
+                        .map(|p| p.join("gcc-ld"))
+                        .find(|p| {
+                            p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
+                        })
+                        .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
+                    cmd.arg({
+                        let mut arg = OsString::from("-B");
+                        arg.push(gcc_ld_dir);
+                        arg
+                    });
+                    cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str()));
                 }
             }
         } else {
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 1574b30..8ca1a60 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -11,6 +11,7 @@
 use crate::base;
 use crate::traits::*;
 
+#[derive(Copy, Clone)]
 pub enum IntPredicate {
     IntEQ,
     IntNE,
@@ -24,6 +25,7 @@
     IntSLE,
 }
 
+#[derive(Copy, Clone)]
 pub enum RealPredicate {
     RealPredicateFalse,
     RealOEQ,
@@ -43,6 +45,7 @@
     RealPredicateTrue,
 }
 
+#[derive(Copy, Clone)]
 pub enum AtomicRmwBinOp {
     AtomicXchg,
     AtomicAdd,
@@ -57,17 +60,17 @@
     AtomicUMin,
 }
 
+#[derive(Copy, Clone)]
 pub enum AtomicOrdering {
-    NotAtomic,
     Unordered,
-    Monotonic,
-    // Consume,  // Not specified yet.
+    Relaxed,
     Acquire,
     Release,
     AcquireRelease,
     SequentiallyConsistent,
 }
 
+#[derive(Copy, Clone)]
 pub enum SynchronizationScope {
     SingleThread,
     CrossThread,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a185eb2..03ef6d5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -22,7 +22,7 @@
 use rustc_span::{sym, Symbol};
 use rustc_symbol_mangling::typeid_for_fnabi;
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, HasDataLayout, WrappingRange};
+use rustc_target::abi::{self, HasDataLayout, InitKind, WrappingRange};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -519,8 +519,9 @@
         intrinsic: Option<Symbol>,
         instance: Option<Instance<'tcx>>,
         source_info: mir::SourceInfo,
-        destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
+        target: Option<mir::BasicBlock>,
         cleanup: Option<mir::BasicBlock>,
+        strict_validity: bool,
     ) -> bool {
         // Emit a panic or a no-op for `assert_*` intrinsics.
         // These are intrinsics that compile to panics so that we can get a message
@@ -543,8 +544,8 @@
             let layout = bx.layout_of(ty);
             let do_panic = match intrinsic {
                 Inhabited => layout.abi.is_uninhabited(),
-                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true),
-                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
+                ZeroValid => !layout.might_permit_raw_init(bx, InitKind::Zero, strict_validity),
+                UninitValid => !layout.might_permit_raw_init(bx, InitKind::Uninit, strict_validity),
             };
             if do_panic {
                 let msg_str = with_no_visible_paths!({
@@ -576,12 +577,12 @@
                     fn_abi,
                     llfn,
                     &[msg.0, msg.1, location],
-                    destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
+                    target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
                     cleanup,
                 );
             } else {
                 // a NOP
-                let target = destination.as_ref().unwrap().1;
+                let target = target.unwrap();
                 helper.funclet_br(self, bx, target)
             }
             true
@@ -597,7 +598,8 @@
         terminator: &mir::Terminator<'tcx>,
         func: &mir::Operand<'tcx>,
         args: &[mir::Operand<'tcx>],
-        destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
+        destination: mir::Place<'tcx>,
+        target: Option<mir::BasicBlock>,
         cleanup: Option<mir::BasicBlock>,
         fn_span: Span,
     ) {
@@ -624,7 +626,7 @@
 
         if let Some(ty::InstanceDef::DropGlue(_, None)) = def {
             // Empty drop glue; a no-op.
-            let &(_, target) = destination.as_ref().unwrap();
+            let target = target.unwrap();
             helper.funclet_br(self, &mut bx, target);
             return;
         }
@@ -653,9 +655,8 @@
         };
 
         if intrinsic == Some(sym::transmute) {
-            if let Some(destination_ref) = destination.as_ref() {
-                let &(dest, target) = destination_ref;
-                self.codegen_transmute(&mut bx, &args[0], dest);
+            if let Some(target) = target {
+                self.codegen_transmute(&mut bx, &args[0], destination);
                 helper.funclet_br(self, &mut bx, target);
             } else {
                 // If we are trying to transmute to an uninhabited type,
@@ -676,8 +677,9 @@
             intrinsic,
             instance,
             source_info,
-            destination,
+            target,
             cleanup,
+            self.cx.tcx().sess.opts.debugging_opts.strict_init_checks,
         ) {
             return;
         }
@@ -687,15 +689,15 @@
         let mut llargs = Vec::with_capacity(arg_count);
 
         // Prepare the return value destination
-        let ret_dest = if let Some((dest, _)) = *destination {
+        let ret_dest = if target.is_some() {
             let is_intrinsic = intrinsic.is_some();
-            self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic)
+            self.make_return_dest(&mut bx, destination, &fn_abi.ret, &mut llargs, is_intrinsic)
         } else {
             ReturnDest::Nothing
         };
 
         if intrinsic == Some(sym::caller_location) {
-            if let Some((_, target)) = destination.as_ref() {
+            if let Some(target) = target {
                 let location = self
                     .get_caller_location(&mut bx, mir::SourceInfo { span: fn_span, ..source_info });
 
@@ -703,7 +705,7 @@
                     location.val.store(&mut bx, tmp);
                 }
                 self.store_return(&mut bx, ret_dest, &fn_abi.ret, location.immediate());
-                helper.funclet_br(self, &mut bx, *target);
+                helper.funclet_br(self, &mut bx, target);
             }
             return;
         }
@@ -766,7 +768,7 @@
                     self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval);
                 }
 
-                if let Some((_, target)) = *destination {
+                if let Some(target) = target {
                     helper.funclet_br(self, &mut bx, target);
                 } else {
                     bx.unreachable();
@@ -913,7 +915,7 @@
                 fn_abi,
                 fn_ptr,
                 &llargs,
-                destination.as_ref().map(|&(_, target)| (ret_dest, target)),
+                target.as_ref().map(|&target| (ret_dest, target)),
                 cleanup,
             );
 
@@ -930,7 +932,7 @@
             fn_abi,
             fn_ptr,
             &llargs,
-            destination.as_ref().map(|&(_, target)| (ret_dest, target)),
+            target.as_ref().map(|&target| (ret_dest, target)),
             cleanup,
         );
     }
@@ -1083,7 +1085,8 @@
             mir::TerminatorKind::Call {
                 ref func,
                 ref args,
-                ref destination,
+                destination,
+                target,
                 cleanup,
                 from_hir_call: _,
                 fn_span,
@@ -1095,6 +1098,7 @@
                     func,
                     args,
                     destination,
+                    target,
                     cleanup,
                     fn_span,
                 );
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 6d6d3ae..0ed4c3f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -388,17 +388,17 @@
                     2 => (SequentiallyConsistent, SequentiallyConsistent),
                     3 => match split[2] {
                         "unordered" => (Unordered, Unordered),
-                        "relaxed" => (Monotonic, Monotonic),
+                        "relaxed" => (Relaxed, Relaxed),
                         "acq" => (Acquire, Acquire),
-                        "rel" => (Release, Monotonic),
+                        "rel" => (Release, Relaxed),
                         "acqrel" => (AcquireRelease, Acquire),
-                        "failrelaxed" if is_cxchg => (SequentiallyConsistent, Monotonic),
+                        "failrelaxed" if is_cxchg => (SequentiallyConsistent, Relaxed),
                         "failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
                         _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
                     },
                     4 => match (split[2], split[3]) {
-                        ("acq", "failrelaxed") if is_cxchg => (Acquire, Monotonic),
-                        ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Monotonic),
+                        ("acq", "failrelaxed") if is_cxchg => (Acquire, Relaxed),
+                        ("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Relaxed),
                         _ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
                     },
                     _ => bx.sess().fatal("Atomic intrinsic not in correct format"),
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index d7cbc48..0c20324 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -60,7 +60,7 @@
     ecx.push_stack_frame(
         cid.instance,
         body,
-        Some(&ret.into()),
+        &ret.into(),
         StackPopCleanup::Root { cleanup: false },
     )?;
 
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 9e5b004..9de5541 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -265,7 +265,8 @@
         instance: ty::Instance<'tcx>,
         _abi: Abi,
         args: &[OpTy<'tcx>],
-        _ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>,
+        _dest: &PlaceTy<'tcx>,
+        _ret: Option<mir::BasicBlock>,
         _unwind: StackPopUnwind, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         debug!("find_mir_or_eval_fn: {:?}", instance);
@@ -293,6 +294,7 @@
                     new_instance,
                     _abi,
                     args,
+                    _dest,
                     _ret,
                     _unwind,
                 )?
@@ -307,17 +309,18 @@
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>,
+        dest: &PlaceTy<'tcx, Self::PointerTag>,
+        target: Option<mir::BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<'tcx> {
         // Shared intrinsics.
-        if ecx.emulate_intrinsic(instance, args, ret)? {
+        if ecx.emulate_intrinsic(instance, args, dest, target)? {
             return Ok(());
         }
         let intrinsic_name = ecx.tcx.item_name(instance.def_id());
 
         // CTFE-specific intrinsics.
-        let Some((dest, ret)) = ret else {
+        let Some(ret) = target else {
             return Err(ConstEvalErrKind::NeedsRfc(format!(
                 "calling intrinsic `{}`",
                 intrinsic_name
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index dfb81a2..4c84bd0 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -105,7 +105,7 @@
 
     /// The location where the result of the current stack frame should be written to,
     /// and its layout in the caller.
-    pub return_place: Option<PlaceTy<'tcx, Tag>>,
+    pub return_place: PlaceTy<'tcx, Tag>,
 
     /// The list of locals for this stack frame, stored in order as
     /// `[return_ptr, arguments..., variables..., temporaries...]`.
@@ -676,7 +676,7 @@
         &mut self,
         instance: ty::Instance<'tcx>,
         body: &'mir mir::Body<'tcx>,
-        return_place: Option<&PlaceTy<'tcx, M::PointerTag>>,
+        return_place: &PlaceTy<'tcx, M::PointerTag>,
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
@@ -685,7 +685,7 @@
             body,
             loc: Err(body.span), // Span used for errors caused during preamble.
             return_to_block,
-            return_place: return_place.copied(),
+            return_place: *return_place,
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
@@ -807,14 +807,9 @@
             self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
 
         if !unwinding {
-            // Copy the return value to the caller's stack frame.
-            if let Some(ref return_place) = frame.return_place {
-                let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
-                self.copy_op_transmute(&op, return_place)?;
-                trace!("{:?}", self.dump_place(**return_place));
-            } else {
-                throw_ub!(Unreachable);
-            }
+            let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
+            self.copy_op_transmute(&op, &frame.return_place)?;
+            trace!("{:?}", self.dump_place(*frame.return_place));
         }
 
         let return_to_block = frame.return_to_block;
@@ -1055,7 +1050,7 @@
         body.hash_stable(hcx, hasher);
         instance.hash_stable(hcx, hasher);
         return_to_block.hash_stable(hcx, hasher);
-        return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
+        return_place.hash_stable(hcx, hasher);
         locals.hash_stable(hcx, hasher);
         loc.hash_stable(hcx, hasher);
         extra.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 5e0d1ab..bf1cf81 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -15,7 +15,7 @@
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, Align, Primitive, Size};
+use rustc_target::abi::{Abi, Align, InitKind, Primitive, Size};
 
 use super::{
     util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
@@ -115,13 +115,14 @@
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, M::PointerTag>],
-        ret: Option<(&PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
+        dest: &PlaceTy<'tcx, M::PointerTag>,
+        ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, bool> {
         let substs = instance.substs;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
 
         // First handle intrinsics without return place.
-        let (dest, ret) = match ret {
+        let ret = match ret {
             None => match intrinsic_name {
                 sym::transmute => throw_ub_format!("transmuting to uninhabited type"),
                 sym::abort => M::abort(self, "the program aborted execution".to_owned())?,
@@ -407,7 +408,11 @@
                     )?;
                 }
                 if intrinsic_name == sym::assert_zero_valid
-                    && !layout.might_permit_raw_init(self, /*zero:*/ true)
+                    && !layout.might_permit_raw_init(
+                        self,
+                        InitKind::Zero,
+                        self.tcx.sess.opts.debugging_opts.strict_init_checks,
+                    )
                 {
                     M::abort(
                         self,
@@ -418,7 +423,11 @@
                     )?;
                 }
                 if intrinsic_name == sym::assert_uninit_valid
-                    && !layout.might_permit_raw_init(self, /*zero:*/ false)
+                    && !layout.might_permit_raw_init(
+                        self,
+                        InitKind::Uninit,
+                        self.tcx.sess.opts.debugging_opts.strict_init_checks,
+                    )
                 {
                     M::abort(
                         self,
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 1dcd50a..3572a9c 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -169,7 +169,8 @@
         instance: ty::Instance<'tcx>,
         abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
-        ret: Option<(&PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
+        destination: &PlaceTy<'tcx, Self::PointerTag>,
+        target: Option<mir::BasicBlock>,
         unwind: StackPopUnwind,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
 
@@ -180,7 +181,8 @@
         fn_val: Self::ExtraFnVal,
         abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
-        ret: Option<(&PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
+        destination: &PlaceTy<'tcx, Self::PointerTag>,
+        target: Option<mir::BasicBlock>,
         unwind: StackPopUnwind,
     ) -> InterpResult<'tcx>;
 
@@ -190,7 +192,8 @@
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::PointerTag>],
-        ret: Option<(&PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
+        destination: &PlaceTy<'tcx, Self::PointerTag>,
+        target: Option<mir::BasicBlock>,
         unwind: StackPopUnwind,
     ) -> InterpResult<'tcx>;
 
@@ -470,7 +473,8 @@
         fn_val: !,
         _abi: Abi,
         _args: &[OpTy<$tcx>],
-        _ret: Option<(&PlaceTy<$tcx>, mir::BasicBlock)>,
+        _destination: &PlaceTy<$tcx, Self::PointerTag>,
+        _target: Option<mir::BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<$tcx> {
         match fn_val {}
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 25f9d4b..a5c7d4c 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -57,7 +57,15 @@
                 self.go_to_block(target_block);
             }
 
-            Call { ref func, ref args, destination, ref cleanup, from_hir_call: _, fn_span: _ } => {
+            Call {
+                ref func,
+                ref args,
+                destination,
+                target,
+                ref cleanup,
+                from_hir_call: _,
+                fn_span: _,
+            } => {
                 let old_stack = self.frame_idx();
                 let old_loc = self.frame().loc;
                 let func = self.eval_operand(func, None)?;
@@ -91,20 +99,14 @@
                     ),
                 };
 
-                let dest_place;
-                let ret = match destination {
-                    Some((dest, ret)) => {
-                        dest_place = self.eval_place(dest)?;
-                        Some((&dest_place, ret))
-                    }
-                    None => None,
-                };
+                let destination = self.eval_place(destination)?;
                 self.eval_fn_call(
                     fn_val,
                     (fn_sig.abi, fn_abi),
                     &args,
                     with_caller_location,
-                    ret,
+                    &destination,
+                    target,
                     match (cleanup, fn_abi.can_unwind) {
                         (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup),
                         (None, true) => StackPopUnwind::Skip,
@@ -299,7 +301,8 @@
         (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
         args: &[OpTy<'tcx, M::PointerTag>],
         with_caller_location: bool,
-        ret: Option<(&PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
+        destination: &PlaceTy<'tcx, M::PointerTag>,
+        target: Option<mir::BasicBlock>,
         mut unwind: StackPopUnwind,
     ) -> InterpResult<'tcx> {
         trace!("eval_fn_call: {:#?}", fn_val);
@@ -307,7 +310,15 @@
         let instance = match fn_val {
             FnVal::Instance(instance) => instance,
             FnVal::Other(extra) => {
-                return M::call_extra_fn(self, extra, caller_abi, args, ret, unwind);
+                return M::call_extra_fn(
+                    self,
+                    extra,
+                    caller_abi,
+                    args,
+                    destination,
+                    target,
+                    unwind,
+                );
             }
         };
 
@@ -315,7 +326,7 @@
             ty::InstanceDef::Intrinsic(def_id) => {
                 assert!(self.tcx.is_intrinsic(def_id));
                 // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic.
-                M::call_intrinsic(self, instance, args, ret, unwind)
+                M::call_intrinsic(self, instance, args, destination, target, unwind)
             }
             ty::InstanceDef::VtableShim(..)
             | ty::InstanceDef::ReifyShim(..)
@@ -326,7 +337,7 @@
             | ty::InstanceDef::Item(_) => {
                 // We need MIR for this fn
                 let Some((body, instance)) =
-                    M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? else {
+                    M::find_mir_or_eval_fn(self, instance, caller_abi, args, destination, target, unwind)? else {
                         return Ok(());
                     };
 
@@ -362,8 +373,8 @@
                 self.push_stack_frame(
                     instance,
                     body,
-                    ret.map(|p| p.0),
-                    StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
+                    destination,
+                    StackPopCleanup::Goto { ret: target, unwind },
                 )?;
 
                 // If an error is raised here, pop the frame again to get an accurate backtrace.
@@ -540,7 +551,8 @@
                     (caller_abi, caller_fn_abi),
                     &args,
                     with_caller_location,
-                    ret,
+                    destination,
+                    target,
                     unwind,
                 )
             }
@@ -582,7 +594,8 @@
             (Abi::Rust, fn_abi),
             &[arg.into()],
             false,
-            Some((&dest.into(), target)),
+            &dest.into(),
+            Some(target),
             match unwind {
                 Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
                 None => StackPopUnwind::Skip,
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index f88538f..fc6b8a1 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -788,7 +788,7 @@
             } else {
                 let terminator = self.source[loc.block].terminator_mut();
                 let target = match terminator.kind {
-                    TerminatorKind::Call { destination: Some((_, target)), .. } => target,
+                    TerminatorKind::Call { target: Some(target), .. } => target,
                     ref kind => {
                         span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
                     }
@@ -814,7 +814,8 @@
                             func,
                             args,
                             cleanup: None,
-                            destination: Some((Place::from(new_temp), new_target)),
+                            destination: Place::from(new_temp),
+                            target: Some(new_target),
                             from_hir_call,
                             fn_span,
                         },
@@ -1054,11 +1055,9 @@
         {
             if let Operand::Constant(box Constant { literal, .. }) = func {
                 if let ty::FnDef(def_id, _) = *literal.ty().kind() {
-                    if let Some((destination_place, _)) = destination {
-                        if destination_place == place {
-                            if ccx.tcx.is_const_fn(def_id) {
-                                return true;
-                            }
+                    if destination == place {
+                        if ccx.tcx.is_const_fn(def_id) {
+                            return true;
                         }
                     }
                 }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 3ce33d5..54c2daf 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -673,7 +673,7 @@
                     self.check_edge(location, *unwind, EdgeKind::Unwind);
                 }
             }
-            TerminatorKind::Call { func, args, destination, cleanup, .. } => {
+            TerminatorKind::Call { func, args, destination, target, cleanup, .. } => {
                 let func_ty = func.ty(&self.body.local_decls, self.tcx);
                 match func_ty.kind() {
                     ty::FnPtr(..) | ty::FnDef(..) => {}
@@ -682,7 +682,7 @@
                         format!("encountered non-callable type {} in `Call` terminator", func_ty),
                     ),
                 }
-                if let Some((_, target)) = destination {
+                if let Some(target) = target {
                     self.check_edge(location, *target, EdgeKind::Normal);
                 }
                 if let Some(cleanup) = cleanup {
@@ -693,9 +693,7 @@
                 // passed by a reference to the callee. Consequently they must be non-overlapping.
                 // Currently this simply checks for duplicate places.
                 self.place_cache.clear();
-                if let Some((destination, _)) = destination {
-                    self.place_cache.push(destination.as_ref());
-                }
+                self.place_cache.push(destination.as_ref());
                 for arg in args {
                     if let Operand::Move(place) = arg {
                         self.place_cache.push(place.as_ref());
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 1956327..5a02661 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -319,6 +319,8 @@
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
     (active, cfg_target_abi, "1.55.0", Some(80970), None),
+    /// Allows `cfg(target(abi = "..."))`.
+    (active, cfg_target_compact, "1.63.0", Some(96901), None),
     /// Allows `cfg(target_has_atomic_load_store = "...")`.
     (active, cfg_target_has_atomic, "1.60.0", Some(94039), None),
     /// Allows `cfg(target_has_atomic_equal_alignment = "...")`.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index cebf687..bda7aff 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -343,12 +343,12 @@
     pub span_ext: Span,
 }
 
-impl GenericArgs<'_> {
+impl<'hir> GenericArgs<'hir> {
     pub const fn none() -> Self {
         Self { args: &[], bindings: &[], parenthesized: false, span_ext: DUMMY_SP }
     }
 
-    pub fn inputs(&self) -> &[Ty<'_>] {
+    pub fn inputs(&self) -> &[Ty<'hir>] {
         if self.parenthesized {
             for arg in self.args {
                 match arg {
@@ -549,7 +549,7 @@
         &NOPE
     }
 
-    pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'_>> {
+    pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
         for param in self.params {
             if name == param.name.ident().name {
                 return Some(param);
@@ -608,7 +608,7 @@
     pub fn bounds_for_param(
         &self,
         param_def_id: LocalDefId,
-    ) -> impl Iterator<Item = &WhereBoundPredicate<'_>> {
+    ) -> impl Iterator<Item = &WhereBoundPredicate<'hir>> {
         self.predicates.iter().filter_map(move |pred| match pred {
             WherePredicate::BoundPredicate(bp) if bp.is_param_bound(param_def_id.to_def_id()) => {
                 Some(bp)
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index a18e2d1..76442de 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -24,7 +24,7 @@
 }
 
 /// This is a callback from `rustc_ast` as it cannot access the implicit state
-/// in `rustc_middle` otherwise. It is used to when diagnostic messages are
+/// in `rustc_middle` otherwise. It is used when diagnostic messages are
 /// emitted and stores them in the current query, if there is one.
 fn track_diagnostic(diagnostic: &Diagnostic) {
     tls::with_context_opt(|icx| {
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 8e50515..2ab9489 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -424,10 +424,25 @@
     let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect();
     let mut buffered = lint_buffer.unwrap_or_default();
 
-    if !sess.opts.debugging_opts.no_interleave_lints {
+    if sess.opts.debugging_opts.no_interleave_lints {
+        for (i, pass) in passes.iter_mut().enumerate() {
+            buffered =
+                sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| {
+                    early_lint_node(
+                        sess,
+                        !pre_expansion && i == 0,
+                        lint_store,
+                        registered_tools,
+                        buffered,
+                        EarlyLintPassObjects { lints: slice::from_mut(pass) },
+                        check_node,
+                    )
+                });
+        }
+    } else {
         buffered = early_lint_node(
             sess,
-            pre_expansion,
+            !pre_expansion,
             lint_store,
             registered_tools,
             buffered,
@@ -446,21 +461,6 @@
                 check_node,
             );
         }
-    } else {
-        for (i, pass) in passes.iter_mut().enumerate() {
-            buffered =
-                sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| {
-                    early_lint_node(
-                        sess,
-                        pre_expansion && i == 0,
-                        lint_store,
-                        registered_tools,
-                        buffered,
-                        EarlyLintPassObjects { lints: slice::from_mut(pass) },
-                        check_node,
-                    )
-                });
-        }
     }
 
     // All of the buffered lints should have been emitted at this point.
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f942970..a067534 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -474,7 +474,7 @@
 }
 
 declare_lint! {
-    /// The `unknown_lints` lint detects unrecognized lint attribute.
+    /// The `unknown_lints` lint detects unrecognized lint attributes.
     ///
     /// ### Example
     ///
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index dac3e98..d7daee6 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -13,7 +13,7 @@
 use std::collections::HashMap;
 use std::str::FromStr;
 use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, Type};
-use synstructure::Structure;
+use synstructure::{BindingInfo, Structure};
 
 /// The central struct for constructing the `into_diagnostic` method from an annotated struct.
 pub(crate) struct SessionDiagnosticDerive<'a> {
@@ -71,55 +71,42 @@
                     }
                 };
 
+                // Keep track of which fields are subdiagnostics or have no attributes.
+                let mut subdiagnostics_or_empty = std::collections::HashSet::new();
+
                 // Generates calls to `span_label` and similar functions based on the attributes
                 // on fields. Code for suggestions uses formatting machinery and the value of
                 // other fields - because any given field can be referenced multiple times, it
-                // should be accessed through a borrow. When passing fields to `set_arg` (which
-                // happens below) for Fluent, we want to move the data, so that has to happen
-                // in a separate pass over the fields.
-                let attrs = structure.each(|field_binding| {
-                    let field = field_binding.ast();
-                    let result = field.attrs.iter().map(|attr| {
-                        builder
-                            .generate_field_attr_code(
-                                attr,
-                                FieldInfo {
-                                    vis: &field.vis,
-                                    binding: field_binding,
-                                    ty: &field.ty,
-                                    span: &field.span(),
-                                },
-                            )
-                            .unwrap_or_else(|v| v.to_compile_error())
-                    });
+                // should be accessed through a borrow. When passing fields to `add_subdiagnostic`
+                // or `set_arg` (which happens below) for Fluent, we want to move the data, so that
+                // has to happen in a separate pass over the fields.
+                let attrs = structure
+                    .clone()
+                    .filter(|field_binding| {
+                        let attrs = &field_binding.ast().attrs;
 
-                    quote! { #(#result);* }
-                });
+                        (!attrs.is_empty()
+                            && attrs.iter().all(|attr| {
+                                "subdiagnostic"
+                                    != attr.path.segments.last().unwrap().ident.to_string()
+                            }))
+                            || {
+                                subdiagnostics_or_empty.insert(field_binding.binding.clone());
+                                false
+                            }
+                    })
+                    .each(|field_binding| builder.generate_field_attrs_code(field_binding));
 
-                // When generating `set_arg` calls, move data rather than borrow it to avoid
-                // requiring clones - this must therefore be the last use of each field (for
-                // example, any formatting machinery that might refer to a field should be
-                // generated already).
                 structure.bind_with(|_| synstructure::BindStyle::Move);
-                let args = structure.each(|field_binding| {
-                    let field = field_binding.ast();
-                    // When a field has attributes like `#[label]` or `#[note]` then it doesn't
-                    // need to be passed as an argument to the diagnostic. But when a field has no
-                    // attributes then it must be passed as an argument to the diagnostic so that
-                    // it can be referred to by Fluent messages.
-                    if field.attrs.is_empty() {
-                        let diag = &builder.diag;
-                        let ident = field_binding.ast().ident.as_ref().unwrap();
-                        quote! {
-                            #diag.set_arg(
-                                stringify!(#ident),
-                                #field_binding
-                            );
-                        }
-                    } else {
-                        quote! {}
-                    }
-                });
+                // When a field has attributes like `#[label]` or `#[note]` then it doesn't
+                // need to be passed as an argument to the diagnostic. But when a field has no
+                // attributes or a `#[subdiagnostic]` attribute then it must be passed as an
+                // argument to the diagnostic so that it can be referred to by Fluent messages.
+                let args = structure
+                    .filter(|field_binding| {
+                        subdiagnostics_or_empty.contains(&field_binding.binding)
+                    })
+                    .each(|field_binding| builder.generate_field_attrs_code(field_binding));
 
                 let span = ast.span().unwrap();
                 let (diag, sess) = (&builder.diag, &builder.sess);
@@ -347,36 +334,60 @@
         Ok(tokens.drain(..).collect())
     }
 
-    fn generate_field_attr_code(
-        &mut self,
-        attr: &syn::Attribute,
-        info: FieldInfo<'_>,
-    ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
-        let field_binding = &info.binding.binding;
+    fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
+        let field = binding_info.ast();
+        let field_binding = &binding_info.binding;
 
-        let inner_ty = FieldInnerTy::from_type(&info.ty);
-        let name = attr.path.segments.last().unwrap().ident.to_string();
-        let (binding, needs_destructure) = match (name.as_str(), &inner_ty) {
-            // `primary_span` can accept a `Vec<Span>` so don't destructure that.
-            ("primary_span", FieldInnerTy::Vec(_)) => (quote! { #field_binding.clone() }, false),
-            _ => (quote! { *#field_binding }, true),
-        };
+        let inner_ty = FieldInnerTy::from_type(&field.ty);
 
-        let generated_code = self.generate_inner_field_code(
-            attr,
-            FieldInfo {
-                vis: info.vis,
-                binding: info.binding,
-                ty: inner_ty.inner_type().unwrap_or(&info.ty),
-                span: info.span,
-            },
-            binding,
-        )?;
-
-        if needs_destructure {
-            Ok(inner_ty.with(field_binding, generated_code))
+        // When generating `set_arg` or `add_subdiagnostic` calls, move data rather than
+        // borrow it to avoid requiring clones - this must therefore be the last use of
+        // each field (for example, any formatting machinery that might refer to a field
+        // should be generated already).
+        if field.attrs.is_empty() {
+            let diag = &self.diag;
+            let ident = field.ident.as_ref().unwrap();
+            quote! {
+                #diag.set_arg(
+                    stringify!(#ident),
+                    #field_binding
+                );
+            }
         } else {
-            Ok(generated_code)
+            field
+                .attrs
+                .iter()
+                .map(move |attr| {
+                    let name = attr.path.segments.last().unwrap().ident.to_string();
+                    let (binding, needs_destructure) = match (name.as_str(), &inner_ty) {
+                        // `primary_span` can accept a `Vec<Span>` so don't destructure that.
+                        ("primary_span", FieldInnerTy::Vec(_)) => {
+                            (quote! { #field_binding.clone() }, false)
+                        }
+                        // `subdiagnostics` are not derefed because they are bound by value.
+                        ("subdiagnostic", _) => (quote! { #field_binding }, true),
+                        _ => (quote! { *#field_binding }, true),
+                    };
+
+                    let generated_code = self
+                        .generate_inner_field_code(
+                            attr,
+                            FieldInfo {
+                                binding: binding_info,
+                                ty: inner_ty.inner_type().unwrap_or(&field.ty),
+                                span: &field.span(),
+                            },
+                            binding,
+                        )
+                        .unwrap_or_else(|v| v.to_compile_error());
+
+                    if needs_destructure {
+                        inner_ty.with(field_binding, generated_code)
+                    } else {
+                        generated_code
+                    }
+                })
+                .collect()
         }
     }
 
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index ae5b9db..df01419 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -303,7 +303,6 @@
 
         let inner_ty = FieldInnerTy::from_type(&ast.ty);
         let info = FieldInfo {
-            vis: &ast.vis,
             binding: binding,
             ty: inner_ty.inner_type().unwrap_or(&ast.ty),
             span: &ast.span(),
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index af5a308..636bcf1 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -4,7 +4,7 @@
 use quote::{format_ident, quote, ToTokens};
 use std::collections::BTreeSet;
 use std::str::FromStr;
-use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple, Visibility};
+use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple};
 use synstructure::BindingInfo;
 
 /// Checks whether the type name of `ty` matches `name`.
@@ -158,7 +158,6 @@
 /// Field information passed to the builder. Deliberately omits attrs to discourage the
 /// `generate_*` methods from walking the attributes themselves.
 pub(crate) struct FieldInfo<'a> {
-    pub(crate) vis: &'a Visibility,
     pub(crate) binding: &'a BindingInfo<'a>,
     pub(crate) ty: &'a Type,
     pub(crate) span: &'a proc_macro2::Span,
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index dfc675a..947d563 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -323,7 +323,7 @@
         None
     }
 
-    fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
+    fn verify_no_symbol_conflicts(&self, root: &CrateRoot) -> Result<(), CrateError> {
         // Check for (potential) conflicts with the local crate
         if self.sess.local_stable_crate_id() == root.stable_crate_id() {
             return Err(CrateError::SymbolConflictsCurrent(root.name()));
@@ -342,7 +342,7 @@
 
     fn verify_no_stable_crate_id_hash_conflicts(
         &mut self,
-        root: &CrateRoot<'_>,
+        root: &CrateRoot,
         cnum: CrateNum,
     ) -> Result<(), CrateError> {
         if let Some(existing) = self.cstore.stable_crate_ids.insert(root.stable_crate_id(), cnum) {
@@ -623,7 +623,7 @@
     fn resolve_crate_deps(
         &mut self,
         root: &CratePaths,
-        crate_root: &CrateRoot<'_>,
+        crate_root: &CrateRoot,
         metadata: &MetadataBlob,
         krate: CrateNum,
         dep_kind: CrateDepKind,
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 3df1809..4c5d13d 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -2,6 +2,7 @@
 #![feature(decl_macro)]
 #![feature(drain_filter)]
 #![feature(generators)]
+#![feature(generic_associated_types)]
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(nll)]
@@ -10,6 +11,7 @@
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
 #![feature(slice_as_chunks)]
+#![feature(trusted_len)]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 8d044be..95892d8 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -418,10 +418,11 @@
                             // involved or not, library reordering and kind overriding without
                             // explicit `:rename` in particular.
                             if lib.has_modifiers() || passed_lib.has_modifiers() {
-                                self.tcx.sess.span_err(
-                                    self.tcx.def_span(lib.foreign_module.unwrap()),
-                                    "overriding linking modifiers from command line is not supported"
-                                );
+                                let msg = "overriding linking modifiers from command line is not supported";
+                                match lib.foreign_module {
+                                    Some(def_id) => self.tcx.sess.span_err(self.tcx.def_span(def_id), msg),
+                                    None => self.tcx.sess.err(msg),
+                                };
                             }
                             if passed_lib.kind != NativeLibKind::Unspecified {
                                 lib.kind = passed_lib.kind;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 4038af3..1420871 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1,12 +1,10 @@
 // Decoding metadata from a single crate's metadata
 
 use crate::creader::{CStore, CrateMetadataRef};
-use crate::rmeta::table::{FixedSizeEncoding, Table};
 use crate::rmeta::*;
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
@@ -20,16 +18,14 @@
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_hir::lang_items;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use rustc_middle::middle::stability::DeprecationEntry;
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::thir;
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::GeneratorDiagnosticData;
-use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
+use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
 use rustc_serialize::{opaque, Decodable, Decoder};
 use rustc_session::cstore::{
     CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
@@ -42,6 +38,7 @@
 
 use proc_macro::bridge::client::ProcMacro;
 use std::io;
+use std::iter::TrustedLen;
 use std::mem;
 use std::num::NonZeroUsize;
 use std::path::Path;
@@ -85,21 +82,20 @@
     blob: MetadataBlob,
 
     // --- Some data pre-decoded from the metadata blob, usually for performance ---
-    /// Properties of the whole crate.
     /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
     /// lifetime is only used behind `Lazy`, and therefore acts like a
     /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
     /// is being used to decode those values.
-    root: CrateRoot<'static>,
+    root: CrateRoot,
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
     /// so pre-decoding can probably be avoided.
-    trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<SimplifiedType>)]>>,
+    trait_impls: FxHashMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
     /// Inherent impls which do not follow the normal coherence rules.
     ///
     /// These can be introduced using either `#![rustc_coherence_is_core]`
     /// or `#[rustc_allow_incoherent_impl]`.
-    incoherent_impls: FxHashMap<SimplifiedType, Lazy<[DefIndex]>>,
+    incoherent_impls: FxHashMap<SimplifiedType, LazyArray<DefIndex>>,
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
@@ -265,138 +261,61 @@
     }
 }
 
-impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> {
-    fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
+impl<T: ParameterizedOverTcx> LazyValue<T> {
+    fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(self, metadata: M) -> T::Value<'tcx>
+    where
+        T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
+    {
         let mut dcx = metadata.decoder(self.position.get());
         dcx.lazy_state = LazyState::NodeStart(self.position);
-        T::decode(&mut dcx)
+        T::Value::decode(&mut dcx)
     }
 }
 
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> {
-    fn decode<M: Metadata<'a, 'tcx>>(
+struct DecodeIterator<'a, 'tcx, T> {
+    elem_counter: std::ops::Range<usize>,
+    dcx: DecodeContext<'a, 'tcx>,
+    _phantom: PhantomData<fn() -> T>,
+}
+
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Iterator for DecodeIterator<'a, 'tcx, T> {
+    type Item = T;
+
+    #[inline(always)]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.elem_counter.next().map(|_| T::decode(&mut self.dcx))
+    }
+
+    #[inline(always)]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.elem_counter.size_hint()
+    }
+}
+
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> ExactSizeIterator
+    for DecodeIterator<'a, 'tcx, T>
+{
+    fn len(&self) -> usize {
+        self.elem_counter.len()
+    }
+}
+
+unsafe impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> TrustedLen
+    for DecodeIterator<'a, 'tcx, T>
+{
+}
+
+impl<T: ParameterizedOverTcx> LazyArray<T> {
+    fn decode<'a, 'tcx, M: Metadata<'a, 'tcx>>(
         self,
         metadata: M,
-    ) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
+    ) -> DecodeIterator<'a, 'tcx, T::Value<'tcx>>
+    where
+        T::Value<'tcx>: Decodable<DecodeContext<'a, 'tcx>>,
+    {
         let mut dcx = metadata.decoder(self.position.get());
         dcx.lazy_state = LazyState::NodeStart(self.position);
-        (0..self.meta).map(move |_| T::decode(&mut dcx))
-    }
-}
-
-trait LazyQueryDecodable<'a, 'tcx, T> {
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        err: impl FnOnce() -> !,
-    ) -> T;
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for T {
-    fn decode_query(self, _: CrateMetadataRef<'a>, _: TyCtxt<'tcx>, _: impl FnOnce() -> !) -> T {
-        self
-    }
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for Option<T> {
-    fn decode_query(self, _: CrateMetadataRef<'a>, _: TyCtxt<'tcx>, err: impl FnOnce() -> !) -> T {
-        if let Some(l) = self { l } else { err() }
-    }
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, T> for Option<Lazy<T>>
-where
-    T: Decodable<DecodeContext<'a, 'tcx>>,
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        err: impl FnOnce() -> !,
-    ) -> T {
-        if let Some(l) = self { l.decode((cdata, tcx)) } else { err() }
-    }
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, &'tcx T> for Option<Lazy<T>>
-where
-    T: Decodable<DecodeContext<'a, 'tcx>>,
-    T: ArenaAllocatable<'tcx>,
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        err: impl FnOnce() -> !,
-    ) -> &'tcx T {
-        if let Some(l) = self { tcx.arena.alloc(l.decode((cdata, tcx))) } else { err() }
-    }
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, Option<T>> for Option<Lazy<T>>
-where
-    T: Decodable<DecodeContext<'a, 'tcx>>,
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        _err: impl FnOnce() -> !,
-    ) -> Option<T> {
-        self.map(|l| l.decode((cdata, tcx)))
-    }
-}
-
-impl<'a, 'tcx, T, E> LazyQueryDecodable<'a, 'tcx, Result<Option<T>, E>> for Option<Lazy<T>>
-where
-    T: Decodable<DecodeContext<'a, 'tcx>>,
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        _err: impl FnOnce() -> !,
-    ) -> Result<Option<T>, E> {
-        Ok(self.map(|l| l.decode((cdata, tcx))))
-    }
-}
-
-impl<'a, 'tcx, T> LazyQueryDecodable<'a, 'tcx, &'tcx [T]> for Option<Lazy<[T], usize>>
-where
-    T: Decodable<DecodeContext<'a, 'tcx>> + Copy,
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        _err: impl FnOnce() -> !,
-    ) -> &'tcx [T] {
-        if let Some(l) = self { tcx.arena.alloc_from_iter(l.decode((cdata, tcx))) } else { &[] }
-    }
-}
-
-impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option<DeprecationEntry>>
-    for Option<Lazy<attr::Deprecation>>
-{
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        tcx: TyCtxt<'tcx>,
-        _err: impl FnOnce() -> !,
-    ) -> Option<DeprecationEntry> {
-        self.map(|l| l.decode((cdata, tcx))).map(DeprecationEntry::external)
-    }
-}
-
-impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option<DefId>> for Option<RawDefId> {
-    fn decode_query(
-        self,
-        cdata: CrateMetadataRef<'a>,
-        _: TyCtxt<'tcx>,
-        _: impl FnOnce() -> !,
-    ) -> Option<DefId> {
-        self.map(|raw_def_id| raw_def_id.decode(cdata))
+        DecodeIterator { elem_counter: (0..self.num_elems), dcx, _phantom: PhantomData }
     }
 }
 
@@ -423,7 +342,8 @@
         self.cdata().map_encoded_cnum_to_current(cnum)
     }
 
-    fn read_lazy_with_meta<T: ?Sized + LazyMeta>(&mut self, meta: T::Meta) -> Lazy<T> {
+    #[inline]
+    fn read_lazy_offset_then<T>(&mut self, f: impl Fn(NonZeroUsize) -> T) -> T {
         let distance = self.read_usize();
         let position = match self.lazy_state {
             LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
@@ -434,8 +354,21 @@
             }
             LazyState::Previous(last_pos) => last_pos.get() + distance,
         };
-        self.lazy_state = LazyState::Previous(NonZeroUsize::new(position).unwrap());
-        Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)
+        let position = NonZeroUsize::new(position).unwrap();
+        self.lazy_state = LazyState::Previous(position);
+        f(position)
+    }
+
+    fn read_lazy<T>(&mut self) -> LazyValue<T> {
+        self.read_lazy_offset_then(|pos| LazyValue::from_position(pos))
+    }
+
+    fn read_lazy_array<T>(&mut self, len: usize) -> LazyArray<T> {
+        self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
+    }
+
+    fn read_lazy_table<I, T>(&mut self, len: usize) -> LazyTable<I, T> {
+        self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, len))
     }
 
     #[inline]
@@ -714,36 +647,29 @@
     }
 }
 
-impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
-    for Lazy<T>
-{
+impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
-        decoder.read_lazy_with_meta(())
+        decoder.read_lazy()
     }
 }
 
-impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
-    for Lazy<[T]>
-{
+impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
         let len = decoder.read_usize();
-        if len == 0 { Lazy::empty() } else { decoder.read_lazy_with_meta(len) }
+        if len == 0 { LazyArray::empty() } else { decoder.read_lazy_array(len) }
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for Lazy<Table<I, T>>
-where
-    Option<T>: FixedSizeEncoding,
-{
+impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> {
     fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
         let len = decoder.read_usize();
-        decoder.read_lazy_with_meta(len)
+        decoder.read_lazy_table(len)
     }
 }
 
 implement_ty_decoder!(DecodeContext<'a, 'tcx>);
 
-impl<'tcx> MetadataBlob {
+impl MetadataBlob {
     pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
         MetadataBlob(Lrc::new(metadata_ref))
     }
@@ -753,18 +679,18 @@
     }
 
     pub(crate) fn get_rustc_version(&self) -> String {
-        Lazy::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap())
+        LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap())
             .decode(self)
     }
 
-    pub(crate) fn get_root(&self) -> CrateRoot<'tcx> {
+    pub(crate) fn get_root(&self) -> CrateRoot {
         let slice = &self.blob()[..];
         let offset = METADATA_HEADER.len();
         let pos = (((slice[offset + 0] as u32) << 24)
             | ((slice[offset + 1] as u32) << 16)
             | ((slice[offset + 2] as u32) << 8)
             | ((slice[offset + 3] as u32) << 0)) as usize;
-        Lazy::<CrateRoot<'tcx>>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
+        LazyValue::<CrateRoot>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
     }
 
     pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> {
@@ -791,7 +717,7 @@
     }
 }
 
-impl CrateRoot<'_> {
+impl CrateRoot {
     pub(crate) fn is_proc_macro_crate(&self) -> bool {
         self.proc_macro_data.is_some()
     }
@@ -963,7 +889,7 @@
                 .tables
                 .children
                 .get(self, index)
-                .unwrap_or_else(Lazy::empty)
+                .unwrap_or_else(LazyArray::empty)
                 .decode(self)
                 .map(|index| ty::FieldDef {
                     did: self.local_def_id(index),
@@ -996,7 +922,7 @@
                 .tables
                 .children
                 .get(self, item_id)
-                .unwrap_or_else(Lazy::empty)
+                .unwrap_or_else(LazyArray::empty)
                 .decode(self)
                 .map(|index| self.get_variant(&self.kind(index), index, did))
                 .collect()
@@ -1016,7 +942,7 @@
     }
 
     fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
-        self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self))
+        self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
     }
 
     fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
@@ -1202,7 +1128,7 @@
             .tables
             .children
             .get(self, id)
-            .unwrap_or_else(Lazy::empty)
+            .unwrap_or_else(LazyArray::empty)
             .decode((self, sess))
             .map(move |child_index| self.local_def_id(child_index))
     }
@@ -1278,7 +1204,7 @@
             .tables
             .children
             .get(self, id)
-            .unwrap_or_else(Lazy::empty)
+            .unwrap_or_else(LazyArray::empty)
             .decode(self)
             .map(move |index| respan(self.get_span(index, sess), self.item_name(index)))
     }
@@ -1288,7 +1214,7 @@
             .tables
             .children
             .get(self, id)
-            .unwrap_or_else(Lazy::empty)
+            .unwrap_or_else(LazyArray::empty)
             .decode(self)
             .map(move |field_index| self.get_visibility(field_index))
     }
@@ -1303,7 +1229,7 @@
                 .tables
                 .inherent_impls
                 .get(self, id)
-                .unwrap_or_else(Lazy::empty)
+                .unwrap_or_else(LazyArray::empty)
                 .decode(self)
                 .map(|index| self.local_def_id(index)),
         )
@@ -1318,7 +1244,7 @@
                 .tables
                 .inherent_impls
                 .get(self, ty_index)
-                .unwrap_or_else(Lazy::empty)
+                .unwrap_or_else(LazyArray::empty)
                 .decode(self)
                 .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
         })
@@ -1763,7 +1689,7 @@
         sess: &Session,
         cstore: &CStore,
         blob: MetadataBlob,
-        root: CrateRoot<'static>,
+        root: CrateRoot,
         raw_proc_macros: Option<&'static [ProcMacro]>,
         cnum: CrateNum,
         cnum_map: CrateNumMap,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 065224a..e3581a7 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -1,14 +1,16 @@
-use super::LazyQueryDecodable;
 use crate::creader::{CStore, LoadedMacro};
 use crate::foreign_modules;
 use crate::native_libs;
 
 use rustc_ast as ast;
+use rustc_attr::Deprecation;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
+use rustc_middle::middle::stability::DeprecationEntry;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt, Visibility};
@@ -23,15 +25,80 @@
 use smallvec::SmallVec;
 use std::any::Any;
 
+use super::{Decodable, DecodeContext, DecodeIterator};
+
+trait ProcessQueryValue<'tcx, T> {
+    fn process_decoded(self, _tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> T;
+}
+
+impl<T> ProcessQueryValue<'_, Option<T>> for Option<T> {
+    #[inline(always)]
+    fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<T> {
+        self
+    }
+}
+
+impl<T> ProcessQueryValue<'_, T> for Option<T> {
+    #[inline(always)]
+    fn process_decoded(self, _tcx: TyCtxt<'_>, err: impl Fn() -> !) -> T {
+        if let Some(value) = self { value } else { err() }
+    }
+}
+
+impl<'tcx, T: ArenaAllocatable<'tcx>> ProcessQueryValue<'tcx, &'tcx T> for Option<T> {
+    #[inline(always)]
+    fn process_decoded(self, tcx: TyCtxt<'tcx>, err: impl Fn() -> !) -> &'tcx T {
+        if let Some(value) = self { tcx.arena.alloc(value) } else { err() }
+    }
+}
+
+impl<T, E> ProcessQueryValue<'_, Result<Option<T>, E>> for Option<T> {
+    #[inline(always)]
+    fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Result<Option<T>, E> {
+        Ok(self)
+    }
+}
+
+impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>> ProcessQueryValue<'tcx, &'tcx [T]>
+    for Option<DecodeIterator<'a, 'tcx, T>>
+{
+    #[inline(always)]
+    fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> &'tcx [T] {
+        if let Some(iter) = self { tcx.arena.alloc_from_iter(iter) } else { &[] }
+    }
+}
+
+impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
+    #[inline(always)]
+    fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
+        self.map(DeprecationEntry::external)
+    }
+}
+
 macro_rules! provide_one {
     (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table }) => {
         provide_one! {
             <$lt> $tcx, $def_id, $other, $cdata, $name => {
-                $cdata.root.tables.$name.get($cdata, $def_id.index).decode_query(
-                    $cdata,
-                    $tcx,
-                    || panic!("{:?} does not have a {:?}", $def_id, stringify!($name)),
-                )
+                $cdata
+                    .root
+                    .tables
+                    .$name
+                    .get($cdata, $def_id.index)
+                    .map(|lazy| lazy.decode(($cdata, $tcx)))
+                    .process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name)))
+            }
+        }
+    };
+    (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => {
+        provide_one! {
+            <$lt> $tcx, $def_id, $other, $cdata, $name => {
+                // We don't decode `table_direct`, since it's not a Lazy, but an actual value
+                $cdata
+                    .root
+                    .tables
+                    .$name
+                    .get($cdata, $def_id.index)
+                    .process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name)))
             }
         }
     };
@@ -143,15 +210,15 @@
     lookup_deprecation_entry => { table }
     visibility => { table }
     unused_generic_params => { table }
-    opt_def_kind => { table }
+    opt_def_kind => { table_direct }
     impl_parent => { table }
-    impl_polarity => { table }
-    impl_defaultness => { table }
-    impl_constness => { table }
+    impl_polarity => { table_direct }
+    impl_defaultness => { table_direct }
+    impl_constness => { table_direct }
     coerce_unsized_info => { table }
     mir_const_qualif => { table }
     rendered_const => { table }
-    asyncness => { table }
+    asyncness => { table_direct }
     fn_arg_names => { table }
     generator_kind => { table }
     trait_def => { table }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 06045bb..15fd190 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -3,6 +3,7 @@
 use crate::rmeta::MetadataBlob;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
+use rustc_middle::parameterized_over_tcx;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_span::def_id::{DefIndex, DefPathHash};
 
@@ -11,6 +12,10 @@
     BorrowedFromTcx(&'tcx DefPathHashMap),
 }
 
+parameterized_over_tcx! {
+    DefPathHashMapRef,
+}
+
 impl DefPathHashMapRef<'_> {
     #[inline]
     pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index e66d226..6310306 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1,5 +1,5 @@
 use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
-use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
+use crate::rmeta::table::TableBuilder;
 use crate::rmeta::*;
 
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -17,7 +17,6 @@
 use rustc_hir::lang_items;
 use rustc_hir::{AnonConst, GenericParamKind};
 use rustc_index::bit_set::GrowableBitSet;
-use rustc_index::vec::Idx;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
@@ -38,6 +37,7 @@
     self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
 };
 use rustc_target::abi::VariantIdx;
+use std::borrow::Borrow;
 use std::hash::Hash;
 use std::num::NonZeroUsize;
 use tracing::{debug, trace};
@@ -47,7 +47,7 @@
     tcx: TyCtxt<'tcx>,
     feat: &'tcx rustc_feature::Features,
 
-    tables: TableBuilders<'tcx>,
+    tables: TableBuilders,
 
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -79,7 +79,7 @@
 macro_rules! empty_proc_macro {
     ($self:ident) => {
         if $self.is_proc_macro {
-            return Lazy::empty();
+            return LazyArray::empty();
         }
     };
 }
@@ -124,33 +124,26 @@
     }
 }
 
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
-    for Lazy<T>
-{
+impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_lazy_distance(*self)
+        e.emit_lazy_distance(self.position)
     }
 }
 
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
-    for Lazy<[T]>
-{
+impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_usize(self.meta)?;
-        if self.meta == 0 {
+        e.emit_usize(self.num_elems)?;
+        if self.num_elems == 0 {
             return Ok(());
         }
-        e.emit_lazy_distance(*self)
+        e.emit_lazy_distance(self.position)
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> Encodable<EncodeContext<'a, 'tcx>> for Lazy<Table<I, T>>
-where
-    Option<T>: FixedSizeEncoding,
-{
+impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_usize(self.meta)?;
-        e.emit_lazy_distance(*self)
+        e.emit_usize(self.encoded_size)?;
+        e.emit_lazy_distance(self.position)
     }
 }
 
@@ -345,34 +338,7 @@
     }
 }
 
-/// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
-trait EncodeContentsForLazy<'a, 'tcx, T: ?Sized + LazyMeta> {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
-}
-
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for &T {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
-        self.encode(ecx).unwrap()
-    }
-}
-
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for T {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
-        self.encode(ecx).unwrap()
-    }
-}
-
-impl<'a, 'tcx, I, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, [T]> for I
-where
-    I: IntoIterator,
-    I::Item: EncodeContentsForLazy<'a, 'tcx, T>,
-{
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
-        self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
-    }
-}
-
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
+// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
 // normally need extra variables to avoid errors about multiple mutable borrows.
 macro_rules! record {
     ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
@@ -384,12 +350,24 @@
     }};
 }
 
+// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// normally need extra variables to avoid errors about multiple mutable borrows.
+macro_rules! record_array {
+    ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
+        {
+            let value = $value;
+            let lazy = $self.lazy_array(value);
+            $self.$tables.$table.set($def_id.index, lazy);
+        }
+    }};
+}
+
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn emit_lazy_distance<T: ?Sized + LazyMeta>(
+    fn emit_lazy_distance(
         &mut self,
-        lazy: Lazy<T>,
+        position: NonZeroUsize,
     ) -> Result<(), <Self as Encoder>::Error> {
-        let pos = lazy.position.get();
+        let pos = position.get();
         let distance = match self.lazy_state {
             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
             LazyState::NodeStart(start) => {
@@ -399,31 +377,50 @@
             }
             LazyState::Previous(last_pos) => {
                 assert!(
-                    last_pos <= lazy.position,
+                    last_pos <= position,
                     "make sure that the calls to `lazy*` \
                      are in the same order as the metadata fields",
                 );
-                lazy.position.get() - last_pos.get()
+                position.get() - last_pos.get()
             }
         };
         self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap());
         self.emit_usize(distance)
     }
 
-    fn lazy<T: ?Sized + LazyMeta>(
-        &mut self,
-        value: impl EncodeContentsForLazy<'a, 'tcx, T>,
-    ) -> Lazy<T> {
+    fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T>
+    where
+        T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
+    {
         let pos = NonZeroUsize::new(self.position()).unwrap();
 
         assert_eq!(self.lazy_state, LazyState::NoNode);
         self.lazy_state = LazyState::NodeStart(pos);
-        let meta = value.encode_contents_for_lazy(self);
+        value.borrow().encode(self).unwrap();
         self.lazy_state = LazyState::NoNode;
 
         assert!(pos.get() <= self.position());
 
-        Lazy::from_position_and_meta(pos, meta)
+        LazyValue::from_position(pos)
+    }
+
+    fn lazy_array<T: ParameterizedOverTcx, I: IntoIterator<Item = B>, B: Borrow<T::Value<'tcx>>>(
+        &mut self,
+        values: I,
+    ) -> LazyArray<T>
+    where
+        T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
+    {
+        let pos = NonZeroUsize::new(self.position()).unwrap();
+
+        assert_eq!(self.lazy_state, LazyState::NoNode);
+        self.lazy_state = LazyState::NodeStart(pos);
+        let len = values.into_iter().map(|value| value.borrow().encode(self).unwrap()).count();
+        self.lazy_state = LazyState::NoNode;
+
+        assert!(pos.get() <= self.position());
+
+        LazyArray::from_position_and_num_elems(pos, len)
     }
 
     fn encode_info_for_items(&mut self) {
@@ -458,13 +455,13 @@
         }
     }
 
-    fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> {
+    fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>> {
         self.lazy(DefPathHashMapRef::BorrowedFromTcx(
             self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(),
         ))
     }
 
-    fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
+    fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> {
         let source_map = self.tcx.sess.source_map();
         let all_source_files = source_map.files();
 
@@ -534,14 +531,16 @@
             })
             .collect::<Vec<_>>();
 
-        self.lazy(adapted.iter().map(|rc| &**rc))
+        self.lazy_array(adapted.iter().map(|rc| &**rc))
     }
 
-    fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
+    fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let tcx = self.tcx;
-        let mut i = self.position();
+        let mut i = 0;
+        let preamble_bytes = self.position() - i;
 
         // Encode the crate deps
+        i = self.position();
         let crate_deps = self.encode_crate_deps();
         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
@@ -567,7 +566,9 @@
         let native_libraries = self.encode_native_libraries();
         let native_lib_bytes = self.position() - i;
 
+        i = self.position();
         let foreign_modules = self.encode_foreign_modules();
+        let foreign_modules_bytes = self.position() - i;
 
         // Encode DefPathTable
         i = self.position();
@@ -587,6 +588,7 @@
         i = self.position();
         let incoherent_impls = self.encode_incoherent_impls();
         let incoherent_impls_bytes = self.position() - i;
+
         // Encode MIR.
         i = self.position();
         self.encode_mir();
@@ -599,6 +601,7 @@
         let item_bytes = self.position() - i;
 
         // Encode the allocation index
+        i = self.position();
         let interpret_alloc_index = {
             let mut interpret_alloc_index = Vec::new();
             let mut n = 0;
@@ -619,8 +622,9 @@
                 }
                 n = new_n;
             }
-            self.lazy(interpret_alloc_index)
+            self.lazy_array(interpret_alloc_index)
         };
+        let interpret_alloc_index_bytes = self.position() - i;
 
         // Encode the proc macro data. This affects 'tables',
         // so we need to do this before we encode the tables
@@ -665,9 +669,9 @@
         let source_map = self.encode_source_map();
         let source_map_bytes = self.position() - i;
 
+        i = self.position();
         let attrs = tcx.hir().krate_attrs();
         let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
-
         let root = self.lazy(CrateRoot {
             name: tcx.crate_name(LOCAL_CRATE),
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
@@ -710,9 +714,34 @@
             expn_hashes,
             def_path_hash_map,
         });
+        let final_bytes = self.position() - i;
 
         let total_bytes = self.position();
 
+        let computed_total_bytes = preamble_bytes
+            + dep_bytes
+            + lib_feature_bytes
+            + lang_item_bytes
+            + diagnostic_item_bytes
+            + native_lib_bytes
+            + foreign_modules_bytes
+            + def_path_table_bytes
+            + traits_bytes
+            + impls_bytes
+            + incoherent_impls_bytes
+            + mir_bytes
+            + item_bytes
+            + interpret_alloc_index_bytes
+            + proc_macro_data_bytes
+            + tables_bytes
+            + debugger_visualizers_bytes
+            + exported_symbols_bytes
+            + hygiene_bytes
+            + def_path_hash_map_bytes
+            + source_map_bytes
+            + final_bytes;
+        assert_eq!(total_bytes, computed_total_bytes);
+
         if tcx.sess.meta_stats() {
             let mut zero_bytes = 0;
             for e in self.opaque.data.iter() {
@@ -721,27 +750,41 @@
                 }
             }
 
-            eprintln!("metadata stats:");
-            eprintln!("                  dep bytes: {}", dep_bytes);
-            eprintln!("          lib feature bytes: {}", lib_feature_bytes);
-            eprintln!("            lang item bytes: {}", lang_item_bytes);
-            eprintln!("      diagnostic item bytes: {}", diagnostic_item_bytes);
-            eprintln!("               native bytes: {}", native_lib_bytes);
-            eprintln!(" debugger visualizers bytes: {}", debugger_visualizers_bytes);
-            eprintln!("           source_map bytes: {}", source_map_bytes);
-            eprintln!("               traits bytes: {}", traits_bytes);
-            eprintln!("                impls bytes: {}", impls_bytes);
-            eprintln!("     incoherent_impls bytes: {}", incoherent_impls_bytes);
-            eprintln!("         exp. symbols bytes: {}", exported_symbols_bytes);
-            eprintln!("       def-path table bytes: {}", def_path_table_bytes);
-            eprintln!("      def-path hashes bytes: {}", def_path_hash_map_bytes);
-            eprintln!("      proc-macro-data-bytes: {}", proc_macro_data_bytes);
-            eprintln!("                  mir bytes: {}", mir_bytes);
-            eprintln!("                 item bytes: {}", item_bytes);
-            eprintln!("                table bytes: {}", tables_bytes);
-            eprintln!("              hygiene bytes: {}", hygiene_bytes);
-            eprintln!("                 zero bytes: {}", zero_bytes);
-            eprintln!("                total bytes: {}", total_bytes);
+            let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
+            let p = |label, bytes| {
+                eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
+            };
+
+            eprintln!("");
+            eprintln!(
+                "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
+                total_bytes,
+                zero_bytes,
+                perc(zero_bytes)
+            );
+            p("preamble", preamble_bytes);
+            p("dep", dep_bytes);
+            p("lib feature", lib_feature_bytes);
+            p("lang item", lang_item_bytes);
+            p("diagnostic item", diagnostic_item_bytes);
+            p("native lib", native_lib_bytes);
+            p("foreign modules", foreign_modules_bytes);
+            p("def-path table", def_path_table_bytes);
+            p("traits", traits_bytes);
+            p("impls", impls_bytes);
+            p("incoherent_impls", incoherent_impls_bytes);
+            p("mir", mir_bytes);
+            p("item", item_bytes);
+            p("interpret_alloc_index", interpret_alloc_index_bytes);
+            p("proc-macro-data", proc_macro_data_bytes);
+            p("tables", tables_bytes);
+            p("debugger visualizers", debugger_visualizers_bytes);
+            p("exported symbols", exported_symbols_bytes);
+            p("hygiene", hygiene_bytes);
+            p("def-path hashes", def_path_hash_map_bytes);
+            p("source_map", source_map_bytes);
+            p("final", final_bytes);
+            eprintln!("");
         }
 
         root
@@ -951,7 +994,7 @@
             .iter()
             .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty()));
 
-        record!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
+        record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
         if attrs.any(|attr| attr.may_have_doc_links()) {
             self.tables.may_have_doc_links.set(def_id.local_def_index, ());
         }
@@ -984,7 +1027,7 @@
             }
             if should_encode_variances(def_kind) {
                 let v = self.tcx.variances_of(def_id);
-                record!(self.tables.variances_of[def_id] <- v);
+                record_array!(self.tables.variances_of[def_id] <- v);
             }
             if should_encode_generics(def_kind) {
                 let g = tcx.generics_of(def_id);
@@ -992,7 +1035,7 @@
                 record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
                 let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
                 if !inferred_outlives.is_empty() {
-                    record!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
+                    record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
                 }
             }
             if let DefKind::Trait | DefKind::TraitAlias = def_kind {
@@ -1004,7 +1047,7 @@
             if implementations.is_empty() {
                 continue;
             }
-            record!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
+            record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
                 assert!(def_id.is_local());
                 def_id.index
             }));
@@ -1031,7 +1074,7 @@
 
         record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
         self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
-        record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
+        record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
             assert!(f.did.is_local());
             f.did.index
         }));
@@ -1079,11 +1122,11 @@
         // items - we encode information about proc-macros later on.
         let reexports = if !self.is_proc_macro {
             match tcx.module_reexports(local_def_id) {
-                Some(exports) => self.lazy(exports),
-                _ => Lazy::empty(),
+                Some(exports) => self.lazy_array(exports),
+                _ => LazyArray::empty(),
             }
         } else {
-            Lazy::empty()
+            LazyArray::empty()
         };
 
         record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
@@ -1091,7 +1134,7 @@
             // Encode this here because we don't do it in encode_def_ids.
             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
         } else {
-            record!(self.tables.children[def_id] <- iter_from_generator(|| {
+            record_array!(self.tables.children[def_id] <- iter_from_generator(|| {
                 for item_id in md.item_ids {
                     match tcx.hir().item(*item_id).kind {
                         // Foreign items are planted into their parent modules
@@ -1156,7 +1199,7 @@
         debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
         let bounds = self.tcx.explicit_item_bounds(def_id);
         if !bounds.is_empty() {
-            record!(self.tables.explicit_item_bounds[def_id] <- bounds);
+            record_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
         }
     }
 
@@ -1188,10 +1231,10 @@
                 let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
                 match *m {
                     hir::TraitFn::Required(ref names) => {
-                        record!(self.tables.fn_arg_names[def_id] <- *names)
+                        record_array!(self.tables.fn_arg_names[def_id] <- *names)
                     }
                     hir::TraitFn::Provided(body) => {
-                        record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
+                        record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
                     }
                 };
                 self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
@@ -1253,7 +1296,7 @@
             ty::AssocKind::Fn => {
                 let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
                 self.tables.asyncness.set(def_id.index, sig.header.asyncness);
-                record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
+                record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
                 // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
                 let constness = if self.tcx.is_const_fn_raw(def_id) {
                     hir::Constness::Const
@@ -1385,7 +1428,7 @@
             }
             hir::ItemKind::Fn(ref sig, .., body) => {
                 self.tables.asyncness.set(def_id.index, sig.header.asyncness);
-                record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
+                record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
                 self.tables.impl_constness.set(def_id.index, sig.header.constness);
                 EntryKind::Fn
             }
@@ -1485,14 +1528,14 @@
         record!(self.tables.kind[def_id] <- entry_kind);
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
-            hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
+            hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <-
                 self.tcx.adt_def(def_id).variants().iter().map(|v| {
                     assert!(v.def_id.is_local());
                     v.def_id.index
                 })
             ),
             hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
-                record!(self.tables.children[def_id] <-
+                record_array!(self.tables.children[def_id] <-
                     self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
                         assert!(f.did.is_local());
                         f.did.index
@@ -1501,7 +1544,7 @@
             }
             hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
-                record!(self.tables.children[def_id] <-
+                record_array!(self.tables.children[def_id] <-
                     associated_item_def_ids.iter().map(|&def_id| {
                         assert!(def_id.is_local());
                         def_id.index
@@ -1583,16 +1626,16 @@
         self.encode_item_type(def_id.to_def_id());
     }
 
-    fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
+    fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
         empty_proc_macro!(self);
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
-        self.lazy(used_libraries.iter())
+        self.lazy_array(used_libraries.iter())
     }
 
-    fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
+    fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {
         empty_proc_macro!(self);
         let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
-        self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned())
+        self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
     }
 
     fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
@@ -1631,7 +1674,7 @@
             let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
             let stability = tcx.lookup_stability(CRATE_DEF_ID);
             let macros =
-                self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
+                self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
             let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
             for (i, span) in spans.into_iter().enumerate() {
                 let span = self.lazy(span);
@@ -1697,12 +1740,12 @@
         }
     }
 
-    fn encode_debugger_visualizers(&mut self) -> Lazy<[DebuggerVisualizerFile]> {
+    fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
         empty_proc_macro!(self);
-        self.lazy(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
+        self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
     }
 
-    fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
+    fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
         empty_proc_macro!(self);
 
         let deps = self
@@ -1734,29 +1777,29 @@
         // the assumption that they are numbered 1 to n.
         // FIXME (#2166): This is not nearly enough to support correct versioning
         // but is enough to get transitive crate dependencies working.
-        self.lazy(deps.iter().map(|&(_, ref dep)| dep))
+        self.lazy_array(deps.iter().map(|&(_, ref dep)| dep))
     }
 
-    fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
+    fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         let lib_features = tcx.lib_features(());
-        self.lazy(lib_features.to_vec())
+        self.lazy_array(lib_features.to_vec())
     }
 
-    fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
+    fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id;
-        self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
+        self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
     }
 
-    fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
+    fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, usize)> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         let lang_items = tcx.lang_items();
         let lang_items = lang_items.items().iter();
-        self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
+        self.lazy_array(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
             if let Some(def_id) = opt_def_id {
                 if def_id.is_local() {
                     return Some((def_id.index, i));
@@ -1766,19 +1809,19 @@
         }))
     }
 
-    fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
+    fn encode_lang_items_missing(&mut self) -> LazyArray<lang_items::LangItem> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        self.lazy(&tcx.lang_items().missing)
+        self.lazy_array(&tcx.lang_items().missing)
     }
 
-    fn encode_traits(&mut self) -> Lazy<[DefIndex]> {
+    fn encode_traits(&mut self) -> LazyArray<DefIndex> {
         empty_proc_macro!(self);
-        self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
+        self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
-    fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
+    fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
         debug!("EncodeContext::encode_traits_and_impls()");
         empty_proc_macro!(self);
         let tcx = self.tcx;
@@ -1817,15 +1860,15 @@
 
                 TraitImpls {
                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
-                    impls: self.lazy(&impls),
+                    impls: self.lazy_array(&impls),
                 }
             })
             .collect();
 
-        self.lazy(&all_impls)
+        self.lazy_array(&all_impls)
     }
 
-    fn encode_incoherent_impls(&mut self) -> Lazy<[IncoherentImpls]> {
+    fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
         debug!("EncodeContext::encode_traits_and_impls()");
         empty_proc_macro!(self);
         let tcx = self.tcx;
@@ -1845,11 +1888,11 @@
                     tcx.hir().def_path_hash(LocalDefId { local_def_index })
                 });
 
-                IncoherentImpls { self_ty: simp, impls: self.lazy(impls) }
+                IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
             })
             .collect();
 
-        self.lazy(&all_impls)
+        self.lazy_array(&all_impls)
     }
 
     // Encodes all symbols exported from this crate into the metadata.
@@ -1861,13 +1904,13 @@
     fn encode_exported_symbols(
         &mut self,
         exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)],
-    ) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportInfo)]> {
+    ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)> {
         empty_proc_macro!(self);
         // The metadata symbol name is special. It should not show up in
         // downstream crates.
         let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
 
-        self.lazy(
+        self.lazy_array(
             exported_symbols
                 .iter()
                 .filter(|&&(ref exported_symbol, _)| match *exported_symbol {
@@ -1878,21 +1921,21 @@
         )
     }
 
-    fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
+    fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
         empty_proc_macro!(self);
         let formats = self.tcx.dependency_formats(());
         for (ty, arr) in formats.iter() {
             if *ty != CrateType::Dylib {
                 continue;
             }
-            return self.lazy(arr.iter().map(|slot| match *slot {
+            return self.lazy_array(arr.iter().map(|slot| match *slot {
                 Linkage::NotLinked | Linkage::IncludedFromDylib => None,
 
                 Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
                 Linkage::Static => Some(LinkagePreference::RequireStatic),
             }));
         }
-        Lazy::empty()
+        LazyArray::empty()
     }
 
     fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
@@ -1903,7 +1946,7 @@
         match nitem.kind {
             hir::ForeignItemKind::Fn(_, ref names, _) => {
                 self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync);
-                record!(self.tables.fn_arg_names[def_id] <- *names);
+                record_array!(self.tables.fn_arg_names[def_id] <- *names);
                 let constness = if self.tcx.is_const_fn_raw(def_id) {
                     hir::Constness::Const
                 } else {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 7ae177c..fb2ffe1 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -1,7 +1,7 @@
 use crate::creader::CrateMetadataRef;
 use decoder::Metadata;
 use def_path_hash_map::DefPathHashMapRef;
-use table::{Table, TableBuilder};
+use table::TableBuilder;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
@@ -20,8 +20,8 @@
 use rustc_middle::thir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::GeneratorDiagnosticData;
 use rustc_middle::ty::{self, ReprOptions, Ty};
+use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
 use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@@ -62,20 +62,6 @@
 /// and further followed by the rustc version string.
 pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
-/// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
-/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
-trait LazyMeta {
-    type Meta: Copy + 'static;
-}
-
-impl<T> LazyMeta for T {
-    type Meta = ();
-}
-
-impl<T> LazyMeta for [T] {
-    type Meta = usize;
-}
-
 /// A value of type T referred to by its absolute position
 /// in the metadata, and which can be decoded lazily.
 ///
@@ -91,8 +77,23 @@
 /// Distances start at 1, as 0-byte nodes are invalid.
 /// Also invalid are nodes being referred in a different
 /// order than they were encoded in.
-///
-/// # Sequences (`Lazy<[T]>`)
+#[must_use]
+struct LazyValue<T> {
+    position: NonZeroUsize,
+    _marker: PhantomData<fn() -> T>,
+}
+
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for LazyValue<T> {
+    type Value<'tcx> = LazyValue<T::Value<'tcx>>;
+}
+
+impl<T> LazyValue<T> {
+    fn from_position(position: NonZeroUsize) -> LazyValue<T> {
+        LazyValue { position, _marker: PhantomData }
+    }
+}
+
+/// A list of lazily-decoded values.
 ///
 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
 /// position, not at the position, which means that the length
@@ -102,39 +103,66 @@
 /// the encoding is that of `Lazy`, with the distinction that
 /// the minimal distance the length of the sequence, i.e.
 /// it's assumed there's no 0-byte element in the sequence.
-#[must_use]
-// FIXME(#59875) the `Meta` parameter only exists to dodge
-// invariance wrt `T` (coming from the `meta: T::Meta` field).
-struct Lazy<T, Meta = <T as LazyMeta>::Meta>
-where
-    T: ?Sized + LazyMeta<Meta = Meta>,
-    Meta: 'static + Copy,
-{
+struct LazyArray<T> {
     position: NonZeroUsize,
-    meta: Meta,
-    _marker: PhantomData<T>,
+    num_elems: usize,
+    _marker: PhantomData<fn() -> T>,
 }
 
-impl<T: ?Sized + LazyMeta> Lazy<T> {
-    fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy<T> {
-        Lazy { position, meta, _marker: PhantomData }
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for LazyArray<T> {
+    type Value<'tcx> = LazyArray<T::Value<'tcx>>;
+}
+
+impl<T> LazyArray<T> {
+    fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray<T> {
+        LazyArray { position, num_elems, _marker: PhantomData }
+    }
+
+    fn empty() -> LazyArray<T> {
+        LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
     }
 }
 
-impl<T> Lazy<T> {
-    fn from_position(position: NonZeroUsize) -> Lazy<T> {
-        Lazy::from_position_and_meta(position, ())
+/// A list of lazily-decoded values, with the added capability of random access.
+///
+/// Random-access table (i.e. offering constant-time `get`/`set`), similar to
+/// `LazyArray<T>`, but without requiring encoding or decoding all the values
+/// eagerly and in-order.
+struct LazyTable<I, T> {
+    position: NonZeroUsize,
+    encoded_size: usize,
+    _marker: PhantomData<fn(I) -> T>,
+}
+
+impl<I: 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for LazyTable<I, T> {
+    type Value<'tcx> = LazyTable<I, T::Value<'tcx>>;
+}
+
+impl<I, T> LazyTable<I, T> {
+    fn from_position_and_encoded_size(
+        position: NonZeroUsize,
+        encoded_size: usize,
+    ) -> LazyTable<I, T> {
+        LazyTable { position, encoded_size, _marker: PhantomData }
     }
 }
 
-impl<T> Lazy<[T]> {
-    fn empty() -> Lazy<[T]> {
-        Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0)
+impl<T> Copy for LazyValue<T> {}
+impl<T> Clone for LazyValue<T> {
+    fn clone(&self) -> Self {
+        *self
     }
 }
 
-impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {}
-impl<T: ?Sized + LazyMeta> Clone for Lazy<T> {
+impl<T> Copy for LazyArray<T> {}
+impl<T> Clone for LazyArray<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<I, T> Copy for LazyTable<I, T> {}
+impl<I, T> Clone for LazyTable<I, T> {
     fn clone(&self) -> Self {
         *self
     }
@@ -155,29 +183,20 @@
     Previous(NonZeroUsize),
 }
 
-// FIXME(#59875) `Lazy!(T)` replaces `Lazy<T>`, passing the `Meta` parameter
-// manually, instead of relying on the default, to get the correct variance.
-// Only needed when `T` itself contains a parameter (e.g. `'tcx`).
-macro_rules! Lazy {
-    (Table<$I:ty, $T:ty>) => {Lazy<Table<$I, $T>, usize>};
-    ([$T:ty]) => {Lazy<[$T], usize>};
-    ($T:ty) => {Lazy<$T, ()>};
-}
-
-type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
-type ExpnDataTable = Lazy<Table<ExpnIndex, Lazy<ExpnData>>>;
-type ExpnHashTable = Lazy<Table<ExpnIndex, Lazy<ExpnHash>>>;
+type SyntaxContextTable = LazyTable<u32, LazyValue<SyntaxContextData>>;
+type ExpnDataTable = LazyTable<ExpnIndex, LazyValue<ExpnData>>;
+type ExpnHashTable = LazyTable<ExpnIndex, LazyValue<ExpnHash>>;
 
 #[derive(MetadataEncodable, MetadataDecodable)]
 pub(crate) struct ProcMacroData {
     proc_macro_decls_static: DefIndex,
     stability: Option<attr::Stability>,
-    macros: Lazy<[DefIndex]>,
+    macros: LazyArray<DefIndex>,
 }
 
 /// Serialized metadata for a crate.
 /// When compiling a proc-macro crate, we encode many of
-/// the `Lazy<[T]>` fields as `Lazy::empty()`. This serves two purposes:
+/// the `LazyArray<T>` fields as `Lazy::empty()`. This serves two purposes:
 ///
 /// 1. We avoid performing unnecessary work. Proc-macro crates can only
 /// export proc-macros functions, which are compiled into a shared library.
@@ -192,7 +211,7 @@
 /// a normal crate, much of what we serialized would be unusable in addition
 /// to being unused.
 #[derive(MetadataEncodable, MetadataDecodable)]
-pub(crate) struct CrateRoot<'tcx> {
+pub(crate) struct CrateRoot {
     name: Symbol,
     triple: TargetTriple,
     extra_filename: String,
@@ -205,32 +224,32 @@
     has_panic_handler: bool,
     has_default_lib_allocator: bool,
 
-    crate_deps: Lazy<[CrateDep]>,
-    dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
-    lib_features: Lazy<[(Symbol, Option<Symbol>)]>,
-    lang_items: Lazy<[(DefIndex, usize)]>,
-    lang_items_missing: Lazy<[lang_items::LangItem]>,
-    diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
-    native_libraries: Lazy<[NativeLib]>,
-    foreign_modules: Lazy<[ForeignModule]>,
-    traits: Lazy<[DefIndex]>,
-    impls: Lazy<[TraitImpls]>,
-    incoherent_impls: Lazy<[IncoherentImpls]>,
-    interpret_alloc_index: Lazy<[u32]>,
+    crate_deps: LazyArray<CrateDep>,
+    dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
+    lib_features: LazyArray<(Symbol, Option<Symbol>)>,
+    lang_items: LazyArray<(DefIndex, usize)>,
+    lang_items_missing: LazyArray<lang_items::LangItem>,
+    diagnostic_items: LazyArray<(Symbol, DefIndex)>,
+    native_libraries: LazyArray<NativeLib>,
+    foreign_modules: LazyArray<ForeignModule>,
+    traits: LazyArray<DefIndex>,
+    impls: LazyArray<TraitImpls>,
+    incoherent_impls: LazyArray<IncoherentImpls>,
+    interpret_alloc_index: LazyArray<u32>,
     proc_macro_data: Option<ProcMacroData>,
 
-    tables: LazyTables<'tcx>,
-    debugger_visualizers: Lazy<[rustc_span::DebuggerVisualizerFile]>,
+    tables: LazyTables,
+    debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>,
 
-    exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportInfo)]),
+    exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
 
     syntax_contexts: SyntaxContextTable,
     expn_data: ExpnDataTable,
     expn_hashes: ExpnHashTable,
 
-    def_path_hash_map: Lazy<DefPathHashMapRef<'tcx>>,
+    def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
 
-    source_map: Lazy<[rustc_span::SourceFile]>,
+    source_map: LazyArray<rustc_span::SourceFile>,
 
     compiler_builtins: bool,
     needs_allocator: bool,
@@ -257,7 +276,12 @@
 }
 
 impl RawDefId {
-    fn decode(self, cdata: CrateMetadataRef<'_>) -> DefId {
+    /// This exists so that `provide_one!` is happy
+    fn decode(self, meta: (CrateMetadataRef<'_>, TyCtxt<'_>)) -> DefId {
+        self.decode_from_cdata(meta.0)
+    }
+
+    fn decode_from_cdata(self, cdata: CrateMetadataRef<'_>) -> DefId {
         let krate = CrateNum::from_u32(self.krate);
         let krate = cdata.map_encoded_cnum_to_current(krate);
         DefId { krate, index: DefIndex::from_u32(self.index) }
@@ -276,30 +300,30 @@
 #[derive(MetadataEncodable, MetadataDecodable)]
 pub(crate) struct TraitImpls {
     trait_id: (u32, DefIndex),
-    impls: Lazy<[(DefIndex, Option<SimplifiedType>)]>,
+    impls: LazyArray<(DefIndex, Option<SimplifiedType>)>,
 }
 
 #[derive(MetadataEncodable, MetadataDecodable)]
 pub(crate) struct IncoherentImpls {
     self_ty: SimplifiedType,
-    impls: Lazy<[DefIndex]>,
+    impls: LazyArray<DefIndex>,
 }
 
 /// Define `LazyTables` and `TableBuilders` at the same time.
 macro_rules! define_tables {
     ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
         #[derive(MetadataEncodable, MetadataDecodable)]
-        pub(crate) struct LazyTables<'tcx> {
-            $($name: Lazy!(Table<$IDX, $T>)),+
+        pub(crate) struct LazyTables {
+            $($name: LazyTable<$IDX, $T>),+
         }
 
         #[derive(Default)]
-        struct TableBuilders<'tcx> {
+        struct TableBuilders {
             $($name: TableBuilder<$IDX, $T>),+
         }
 
-        impl<'tcx> TableBuilders<'tcx> {
-            fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
+        impl TableBuilders {
+            fn encode(&self, buf: &mut Encoder) -> LazyTables {
                 LazyTables {
                     $($name: self.$name.encode(buf)),+
                 }
@@ -309,61 +333,62 @@
 }
 
 define_tables! {
-    kind: Table<DefIndex, Lazy<EntryKind>>,
-    attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
-    children: Table<DefIndex, Lazy<[DefIndex]>>,
+    kind: Table<DefIndex, LazyValue<EntryKind>>,
+    attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
+    children: Table<DefIndex, LazyArray<DefIndex>>,
 
     opt_def_kind: Table<DefIndex, DefKind>,
-    visibility: Table<DefIndex, Lazy<ty::Visibility>>,
-    def_span: Table<DefIndex, Lazy<Span>>,
-    def_ident_span: Table<DefIndex, Lazy<Span>>,
-    lookup_stability: Table<DefIndex, Lazy<attr::Stability>>,
-    lookup_const_stability: Table<DefIndex, Lazy<attr::ConstStability>>,
-    lookup_deprecation_entry: Table<DefIndex, Lazy<attr::Deprecation>>,
+    visibility: Table<DefIndex, LazyValue<ty::Visibility>>,
+    def_span: Table<DefIndex, LazyValue<Span>>,
+    def_ident_span: Table<DefIndex, LazyValue<Span>>,
+    lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
+    lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
+    lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
     // As an optimization, a missing entry indicates an empty `&[]`.
-    explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
-    explicit_predicates_of: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
-    generics_of: Table<DefIndex, Lazy<ty::Generics>>,
+    explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
+    explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
+    generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
     // As an optimization, a missing entry indicates an empty `&[]`.
-    inferred_outlives_of: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
-    super_predicates_of: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
-    type_of: Table<DefIndex, Lazy!(Ty<'tcx>)>,
-    variances_of: Table<DefIndex, Lazy<[ty::Variance]>>,
-    fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
-    codegen_fn_attrs: Table<DefIndex, Lazy!(CodegenFnAttrs)>,
-    impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
-    const_param_default: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
-    optimized_mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
-    mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
-    promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
-    thir_abstract_const: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>,
+    inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
+    super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
+    type_of: Table<DefIndex, LazyValue<Ty<'static>>>,
+    variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
+    fn_sig: Table<DefIndex, LazyValue<ty::PolyFnSig<'static>>>,
+    codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
+    impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'static>>>,
+    const_param_default: Table<DefIndex, LazyValue<rustc_middle::ty::Const<'static>>>,
+    optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
+    mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
+    promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
+    // FIXME(compiler-errors): Why isn't this a LazyArray?
+    thir_abstract_const: Table<DefIndex, LazyValue<&'static [thir::abstract_const::Node<'static>]>>,
     impl_parent: Table<DefIndex, RawDefId>,
     impl_polarity: Table<DefIndex, ty::ImplPolarity>,
     impl_constness: Table<DefIndex, hir::Constness>,
     is_intrinsic: Table<DefIndex, ()>,
     impl_defaultness: Table<DefIndex, hir::Defaultness>,
     // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
-    coerce_unsized_info: Table<DefIndex, Lazy!(ty::adjustment::CoerceUnsizedInfo)>,
-    mir_const_qualif: Table<DefIndex, Lazy!(mir::ConstQualifs)>,
-    rendered_const: Table<DefIndex, Lazy!(String)>,
+    coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
+    mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
+    rendered_const: Table<DefIndex, LazyValue<String>>,
     asyncness: Table<DefIndex, hir::IsAsync>,
-    fn_arg_names: Table<DefIndex, Lazy!([Ident])>,
-    generator_kind: Table<DefIndex, Lazy!(hir::GeneratorKind)>,
-    trait_def: Table<DefIndex, Lazy!(ty::TraitDef)>,
+    fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
+    generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
+    trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
 
     trait_item_def_id: Table<DefIndex, RawDefId>,
-    inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
-    expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
-    unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
-    repr_options: Table<DefIndex, Lazy<ReprOptions>>,
+    inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
+    expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
+    unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>,
+    repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
     // `def_keys` and `def_path_hashes` represent a lazy version of a
     // `DefPathTable`. This allows us to avoid deserializing an entire
     // `DefPathTable` up front, since we may only ever use a few
     // definitions from any given crate.
-    def_keys: Table<DefIndex, Lazy<DefKey>>,
+    def_keys: Table<DefIndex, LazyValue<DefKey>>,
     def_path_hashes: Table<DefIndex, DefPathHash>,
-    proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
-    generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
+    proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
+    generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>,
     may_have_doc_links: Table<DefIndex, ()>,
 }
 
@@ -382,19 +407,19 @@
     OpaqueTy,
     Enum,
     Field,
-    Variant(Lazy<VariantData>),
-    Struct(Lazy<VariantData>),
-    Union(Lazy<VariantData>),
+    Variant(LazyValue<VariantData>),
+    Struct(LazyValue<VariantData>),
+    Union(LazyValue<VariantData>),
     Fn,
     ForeignFn,
-    Mod(Lazy<[ModChild]>),
-    MacroDef(Lazy<ast::MacArgs>, /*macro_rules*/ bool),
+    Mod(LazyArray<ModChild>),
+    MacroDef(LazyValue<ast::MacArgs>, /*macro_rules*/ bool),
     ProcMacro(MacroKind),
     Closure,
     Generator,
     Trait,
     Impl,
-    AssocFn(Lazy<AssocFnData>),
+    AssocFn(LazyValue<AssocFnData>),
     AssocType(AssocContainer),
     AssocConst(AssocContainer),
     TraitAlias,
@@ -464,3 +489,14 @@
     encoder::provide(providers);
     decoder::provide(providers);
 }
+
+trivially_parameterized_over_tcx! {
+    VariantData,
+    AssocFnData,
+    EntryKind,
+    RawDefId,
+    TraitImpls,
+    IncoherentImpls,
+    CrateRoot,
+    CrateDep,
+}
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 53fc2ef..100bac1 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -3,6 +3,7 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_hir::def::{CtorKind, CtorOf};
 use rustc_index::vec::Idx;
+use rustc_middle::ty::ParameterizedOverTcx;
 use rustc_serialize::opaque::Encoder;
 use rustc_serialize::Encoder as _;
 use rustc_span::hygiene::MacroKind;
@@ -201,15 +202,15 @@
 }
 
 // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
-// generic `Lazy<T>` impl, but in the general case we might not need / want to
-// fit every `usize` in `u32`.
-impl<T> FixedSizeEncoding for Option<Lazy<T>> {
+// generic `LazyValue<T>` impl, but in the general case we might not need / want
+// to fit every `usize` in `u32`.
+impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
     type ByteArray = [u8; 4];
 
     #[inline]
     fn from_bytes(b: &[u8; 4]) -> Self {
         let position = NonZeroUsize::new(u32::from_bytes(b) as usize)?;
-        Some(Lazy::from_position(position))
+        Some(LazyValue::from_position(position))
     }
 
     #[inline]
@@ -220,7 +221,7 @@
     }
 }
 
-impl<T> FixedSizeEncoding for Option<Lazy<[T]>> {
+impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
     type ByteArray = [u8; 8];
 
     #[inline]
@@ -228,7 +229,7 @@
         let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
         let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
         let len = u32::from_bytes(meta_bytes) as usize;
-        Some(Lazy::from_position_and_meta(position, len))
+        Some(LazyArray::from_position_and_num_elems(position, len))
     }
 
     #[inline]
@@ -239,28 +240,12 @@
         let position: u32 = position.try_into().unwrap();
         position.write_to_bytes(position_bytes);
 
-        let len = self.map_or(0, |lazy| lazy.meta);
+        let len = self.map_or(0, |lazy| lazy.num_elems);
         let len: u32 = len.try_into().unwrap();
         len.write_to_bytes(meta_bytes);
     }
 }
 
-/// Random-access table (i.e. offering constant-time `get`/`set`), similar to
-/// `Vec<Option<T>>`, but without requiring encoding or decoding all the values
-/// eagerly and in-order.
-/// A total of `(max_idx + 1)` times `Option<T> as FixedSizeEncoding>::ByteArray`
-/// are used for a table, where `max_idx` is the largest index passed to
-/// `TableBuilder::set`.
-pub(super) struct Table<I: Idx, T>
-where
-    Option<T>: FixedSizeEncoding,
-{
-    _marker: PhantomData<(fn(&I), T)>,
-    // NOTE(eddyb) this makes `Table` not implement `Sized`, but no
-    // value of `Table` is ever created (it's always behind `Lazy`).
-    _bytes: [u8],
-}
-
 /// Helper for constructing a table's serialization (also see `Table`).
 pub(super) struct TableBuilder<I: Idx, T>
 where
@@ -296,7 +281,7 @@
         Some(value).write_to_bytes(&mut self.blocks[i]);
     }
 
-    pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> Lazy<Table<I, T>>
+    pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> LazyTable<I, T>
     where
         Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
     {
@@ -305,19 +290,14 @@
             buf.emit_raw_bytes(block).unwrap();
         }
         let num_bytes = self.blocks.len() * N;
-        Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), num_bytes)
+        LazyTable::from_position_and_encoded_size(
+            NonZeroUsize::new(pos as usize).unwrap(),
+            num_bytes,
+        )
     }
 }
 
-impl<I: Idx, T> LazyMeta for Table<I, T>
-where
-    Option<T>: FixedSizeEncoding,
-{
-    /// Number of bytes in the data stream.
-    type Meta = usize;
-}
-
-impl<I: Idx, T> Lazy<Table<I, T>>
+impl<I: Idx, T: ParameterizedOverTcx> LazyTable<I, T>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -327,14 +307,14 @@
         &self,
         metadata: M,
         i: I,
-    ) -> Option<T>
+    ) -> Option<T::Value<'tcx>>
     where
-        Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
+        Option<T::Value<'tcx>>: FixedSizeEncoding<ByteArray = [u8; N]>,
     {
-        debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
+        debug!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
 
         let start = self.position.get();
-        let bytes = &metadata.blob()[start..start + self.meta];
+        let bytes = &metadata.blob()[start..start + self.encoded_size];
         let (bytes, []) = bytes.as_chunks::<N>() else { panic!() };
         let bytes = bytes.get(i.index())?;
         FixedSizeEncoding::from_bytes(bytes)
@@ -343,8 +323,8 @@
     /// Size of the table in entries, including possible gaps.
     pub(super) fn size<const N: usize>(&self) -> usize
     where
-        Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
+        for<'tcx> Option<T::Value<'tcx>>: FixedSizeEncoding<ByteArray = [u8; N]>,
     {
-        self.meta / N
+        self.encoded_size / N
     }
 }
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index b4dd253..3a9fe31 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -33,6 +33,7 @@
 #![feature(discriminant_kind)]
 #![feature(exhaustive_patterns)]
 #![feature(get_mut_unchecked)]
+#![feature(generic_associated_types)]
 #![feature(if_let_guard)]
 #![feature(map_first_last)]
 #![feature(negative_impls)]
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index fb3856b..c859d93 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -250,8 +250,10 @@
         /// This allows the memory occupied by "by-value" arguments to be
         /// reused across function calls without duplicating the contents.
         args: Vec<Operand<'tcx>>,
-        /// Destination for the return value. If none, the call necessarily diverges.
-        destination: Option<(Place<'tcx>, BasicBlock)>,
+        /// Where the returned value will be written
+        destination: Place<'tcx>,
+        /// Where to go after this call returns. If none, the call necessarily diverges.
+        target: Option<BasicBlock>,
         /// Cleanups to be done if the call unwinds.
         cleanup: Option<BasicBlock>,
         /// `true` if this is from a call in HIR rather than from an overloaded
@@ -415,13 +417,13 @@
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call { destination: None, cleanup: None, .. }
+            | Call { target: None, cleanup: None, .. }
             | InlineAsm { destination: None, cleanup: None, .. } => {
                 None.into_iter().chain((&[]).into_iter().copied())
             }
             Goto { target: t }
-            | Call { destination: None, cleanup: Some(t), .. }
-            | Call { destination: Some((_, t)), cleanup: None, .. }
+            | Call { target: None, cleanup: Some(t), .. }
+            | Call { target: Some(t), cleanup: None, .. }
             | Yield { resume: t, drop: None, .. }
             | DropAndReplace { target: t, unwind: None, .. }
             | Drop { target: t, unwind: None, .. }
@@ -431,7 +433,7 @@
             | InlineAsm { destination: None, cleanup: Some(t), .. } => {
                 Some(t).into_iter().chain((&[]).into_iter().copied())
             }
-            Call { destination: Some((_, t)), cleanup: Some(ref u), .. }
+            Call { target: Some(t), cleanup: Some(ref u), .. }
             | Yield { resume: t, drop: Some(ref u), .. }
             | DropAndReplace { target: t, unwind: Some(ref u), .. }
             | Drop { target: t, unwind: Some(ref u), .. }
@@ -457,11 +459,11 @@
             | GeneratorDrop
             | Return
             | Unreachable
-            | Call { destination: None, cleanup: None, .. }
+            | Call { target: None, cleanup: None, .. }
             | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
             Goto { target: ref mut t }
-            | Call { destination: None, cleanup: Some(ref mut t), .. }
-            | Call { destination: Some((_, ref mut t)), cleanup: None, .. }
+            | Call { target: None, cleanup: Some(ref mut t), .. }
+            | Call { target: Some(ref mut t), cleanup: None, .. }
             | Yield { resume: ref mut t, drop: None, .. }
             | DropAndReplace { target: ref mut t, unwind: None, .. }
             | Drop { target: ref mut t, unwind: None, .. }
@@ -471,7 +473,7 @@
             | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => {
                 Some(t).into_iter().chain(&mut [])
             }
-            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
+            Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. }
             | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
             | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
             | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
@@ -590,9 +592,7 @@
                 write!(fmt, "replace({:?} <- {:?})", place, value)
             }
             Call { func, args, destination, .. } => {
-                if let Some((destination, _)) = destination {
-                    write!(fmt, "{:?} = ", destination)?;
-                }
+                write!(fmt, "{:?} = ", destination)?;
                 write!(fmt, "{:?}(", func)?;
                 for (index, arg) in args.iter().enumerate() {
                     if index > 0 {
@@ -683,12 +683,12 @@
                     .chain(iter::once("otherwise".into()))
                     .collect()
             }),
-            Call { destination: Some(_), cleanup: Some(_), .. } => {
+            Call { target: Some(_), cleanup: Some(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            Call { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
-            Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            Call { destination: None, cleanup: None, .. } => vec![],
+            Call { target: Some(_), cleanup: None, .. } => vec!["return".into()],
+            Call { target: None, cleanup: Some(_), .. } => vec!["unwind".into()],
+            Call { target: None, cleanup: None, .. } => vec![],
             Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
             Yield { drop: None, .. } => vec!["resume".into()],
             DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 901f3bf..14d4cb2 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -44,20 +44,15 @@
                 resume_arg: resume_arg.try_fold_with(folder)?,
                 drop,
             },
-            Call { func, args, destination, cleanup, from_hir_call, fn_span } => {
-                let dest = destination
-                    .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest))))
-                    .transpose()?;
-
-                Call {
-                    func: func.try_fold_with(folder)?,
-                    args: args.try_fold_with(folder)?,
-                    destination: dest,
-                    cleanup,
-                    from_hir_call,
-                    fn_span,
-                }
-            }
+            Call { func, args, destination, target, cleanup, from_hir_call, fn_span } => Call {
+                func: func.try_fold_with(folder)?,
+                args: args.try_fold_with(folder)?,
+                destination: destination.try_fold_with(folder)?,
+                target,
+                cleanup,
+                from_hir_call,
+                fn_span,
+            },
             Assert { cond, expected, msg, target, cleanup } => {
                 use AssertKind::*;
                 let msg = match msg {
@@ -113,9 +108,7 @@
             }
             Yield { ref value, .. } => value.visit_with(visitor),
             Call { ref func, ref args, ref destination, .. } => {
-                if let Some((ref loc, _)) = *destination {
-                    loc.visit_with(visitor)?;
-                };
+                destination.visit_with(visitor)?;
                 func.visit_with(visitor)?;
                 args.visit_with(visitor)
             }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index ef4f1f5..d0d7f12 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -534,6 +534,7 @@
                         func,
                         args,
                         destination,
+                        target: _,
                         cleanup: _,
                         from_hir_call: _,
                         fn_span: _
@@ -542,13 +543,11 @@
                         for arg in args {
                             self.visit_operand(arg, location);
                         }
-                        if let Some((destination, _)) = destination {
-                            self.visit_place(
-                                destination,
-                                PlaceContext::MutatingUse(MutatingUseContext::Call),
-                                location
-                            );
-                        }
+                        self.visit_place(
+                            destination,
+                            PlaceContext::MutatingUse(MutatingUseContext::Call),
+                            location
+                        );
                     }
 
                     TerminatorKind::Assert {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index de4cc67..f7ced06 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,8 +1,10 @@
 use crate::mir::Mutability;
+use crate::ty::subst::GenericArgKind;
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_hir::def_id::DefId;
 use std::fmt::Debug;
 use std::hash::Hash;
+use std::iter;
 
 use self::SimplifiedTypeGen::*;
 
@@ -72,6 +74,10 @@
 
 /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
 ///
+/// **This function should only be used if you need to store or retrieve the type from some
+/// hashmap. If you want to quickly decide whether two types may unify, use the [DeepRejectCtxt]
+/// instead.**
+///
 /// The idea is to get something simple that we can use to quickly decide if two types could unify,
 /// for example during method lookup. If this function returns `Some(x)` it can only unify with
 /// types for which this method returns either `Some(x)` as well or `None`.
@@ -182,3 +188,218 @@
         }
     }
 }
+
+/// Given generic arguments from an obligation and an impl,
+/// could these two be unified after replacing parameters in the
+/// the impl with inference variables.
+///
+/// For obligations, parameters won't be replaced by inference
+/// variables and only unify with themselves. We treat them
+/// the same way we treat placeholders.
+///
+/// We also use this function during coherence. For coherence the
+/// impls only have to overlap for some value, so we treat parameters
+/// on both sides like inference variables. This behavior is toggled
+/// using the `treat_obligation_params` field.
+#[derive(Debug, Clone, Copy)]
+pub struct DeepRejectCtxt {
+    pub treat_obligation_params: TreatParams,
+}
+
+impl DeepRejectCtxt {
+    pub fn generic_args_may_unify(
+        self,
+        obligation_arg: ty::GenericArg<'_>,
+        impl_arg: ty::GenericArg<'_>,
+    ) -> bool {
+        match (obligation_arg.unpack(), impl_arg.unpack()) {
+            // We don't fast reject based on regions for now.
+            (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
+            (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
+                self.types_may_unify(obl, imp)
+            }
+            (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
+                self.consts_may_unify(obl, imp)
+            }
+            _ => bug!("kind mismatch: {obligation_arg} {impl_arg}"),
+        }
+    }
+
+    pub fn types_may_unify(self, obligation_ty: Ty<'_>, impl_ty: Ty<'_>) -> bool {
+        match impl_ty.kind() {
+            // Start by checking whether the type in the impl may unify with
+            // pretty much everything. Just return `true` in that case.
+            ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
+            // These types only unify with inference variables or their own
+            // variant.
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(..)
+            | ty::Str
+            | ty::Array(..)
+            | ty::Slice(..)
+            | ty::RawPtr(..)
+            | ty::Dynamic(..)
+            | ty::Ref(..)
+            | ty::Never
+            | ty::Tuple(..)
+            | ty::FnPtr(..)
+            | ty::Foreign(..)
+            | ty::Opaque(..) => {}
+            ty::FnDef(..)
+            | ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
+            | ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"),
+        }
+
+        let k = impl_ty.kind();
+        match *obligation_ty.kind() {
+            // Purely rigid types, use structural equivalence.
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Str
+            | ty::Never
+            | ty::Foreign(_) => obligation_ty == impl_ty,
+            ty::Ref(_, obl_ty, obl_mutbl) => match k {
+                &ty::Ref(_, impl_ty, impl_mutbl) => {
+                    obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty)
+                }
+                _ => false,
+            },
+            ty::Adt(obl_def, obl_substs) => match k {
+                &ty::Adt(impl_def, impl_substs) => {
+                    obl_def == impl_def
+                        && iter::zip(obl_substs, impl_substs)
+                            .all(|(obl, imp)| self.generic_args_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+            ty::Slice(obl_ty) => {
+                matches!(k, &ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty))
+            }
+            ty::Array(obl_ty, obl_len) => match k {
+                &ty::Array(impl_ty, impl_len) => {
+                    self.types_may_unify(obl_ty, impl_ty)
+                        && self.consts_may_unify(obl_len, impl_len)
+                }
+                _ => false,
+            },
+            ty::Tuple(obl) => match k {
+                &ty::Tuple(imp) => {
+                    obl.len() == imp.len()
+                        && iter::zip(obl, imp).all(|(obl, imp)| self.types_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+            ty::RawPtr(obl) => match k {
+                ty::RawPtr(imp) => obl.mutbl == imp.mutbl && self.types_may_unify(obl.ty, imp.ty),
+                _ => false,
+            },
+            ty::Dynamic(obl_preds, ..) => {
+                // Ideally we would walk the existential predicates here or at least
+                // compare their length. But considering that the relevant `Relate` impl
+                // actually sorts and deduplicates these, that doesn't work.
+                matches!(k, ty::Dynamic(impl_preds, ..) if
+                    obl_preds.principal_def_id() == impl_preds.principal_def_id()
+                )
+            }
+            ty::FnPtr(obl_sig) => match k {
+                ty::FnPtr(impl_sig) => {
+                    let ty::FnSig { inputs_and_output, c_variadic, unsafety, abi } =
+                        obl_sig.skip_binder();
+                    let impl_sig = impl_sig.skip_binder();
+
+                    abi == impl_sig.abi
+                        && c_variadic == impl_sig.c_variadic
+                        && unsafety == impl_sig.unsafety
+                        && inputs_and_output.len() == impl_sig.inputs_and_output.len()
+                        && iter::zip(inputs_and_output, impl_sig.inputs_and_output)
+                            .all(|(obl, imp)| self.types_may_unify(obl, imp))
+                }
+                _ => false,
+            },
+
+            // Opaque types in impls should be forbidden, but that doesn't
+            // stop compilation. So this match arm should never return true
+            // if compilation succeeds.
+            ty::Opaque(..) => matches!(k, ty::Opaque(..)),
+
+            // Impls cannot contain these types as these cannot be named directly.
+            ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
+
+            ty::Placeholder(..) => false,
+
+            // Depending on the value of `treat_obligation_params`, we either
+            // treat generic parameters like placeholders or like inference variables.
+            ty::Param(_) => match self.treat_obligation_params {
+                TreatParams::AsPlaceholder => false,
+                TreatParams::AsInfer => true,
+            },
+
+            ty::Infer(_) => true,
+
+            // As we're walking the whole type, it may encounter projections
+            // inside of binders and what not, so we're just going to assume that
+            // projections can unify with other stuff.
+            //
+            // Looking forward to lazy normalization this is the safer strategy anyways.
+            ty::Projection(_) => true,
+
+            ty::Error(_) => true,
+
+            ty::GeneratorWitness(..) | ty::Bound(..) => {
+                bug!("unexpected obligation type: {:?}", obligation_ty)
+            }
+        }
+    }
+
+    pub fn consts_may_unify(self, obligation_ct: ty::Const<'_>, impl_ct: ty::Const<'_>) -> bool {
+        match impl_ct.val() {
+            ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
+                return true;
+            }
+            ty::ConstKind::Value(_) => {}
+            ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+                bug!("unexpected impl arg: {:?}", impl_ct)
+            }
+        }
+
+        let k = impl_ct.val();
+        match obligation_ct.val() {
+            ty::ConstKind::Param(_) => match self.treat_obligation_params {
+                TreatParams::AsPlaceholder => false,
+                TreatParams::AsInfer => true,
+            },
+
+            // As we don't necessarily eagerly evaluate constants,
+            // they might unify with any value.
+            ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true,
+            ty::ConstKind::Value(obl) => match k {
+                ty::ConstKind::Value(imp) => {
+                    // FIXME(valtrees): Once we have valtrees, we can just
+                    // compare them directly here.
+                    match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) {
+                        (Some(obl), Some(imp)) => obl == imp,
+                        _ => true,
+                    }
+                }
+                _ => true,
+            },
+
+            ty::ConstKind::Infer(_) => true,
+
+            ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+                bug!("unexpected obl const: {:?}", obligation_ct)
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 775b06c..b61a382 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -72,6 +72,7 @@
 };
 pub use self::instance::{Instance, InstanceDef};
 pub use self::list::List;
+pub use self::parameterized::ParameterizedOverTcx;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::RegionKind::*;
@@ -119,6 +120,7 @@
 mod impls_ty;
 mod instance;
 mod list;
+mod parameterized;
 mod rvalue_scopes;
 mod structural_impls;
 mod sty;
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
new file mode 100644
index 0000000..54ba9e8
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -0,0 +1,119 @@
+use rustc_hir::def_id::DefId;
+use rustc_index::vec::{Idx, IndexVec};
+
+use crate::middle::exported_symbols::ExportedSymbol;
+use crate::mir::Body;
+use crate::thir::abstract_const::Node;
+use crate::ty::{
+    self, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
+};
+
+pub trait ParameterizedOverTcx: 'static {
+    #[allow(unused_lifetimes)]
+    type Value<'tcx>;
+}
+
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for &'static [T] {
+    type Value<'tcx> = &'tcx [T::Value<'tcx>];
+}
+
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for Option<T> {
+    type Value<'tcx> = Option<T::Value<'tcx>>;
+}
+
+impl<A: ParameterizedOverTcx, B: ParameterizedOverTcx> ParameterizedOverTcx for (A, B) {
+    type Value<'tcx> = (A::Value<'tcx>, B::Value<'tcx>);
+}
+
+impl<I: Idx + 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for IndexVec<I, T> {
+    type Value<'tcx> = IndexVec<I, T::Value<'tcx>>;
+}
+
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> {
+    type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>;
+}
+
+#[macro_export]
+macro_rules! trivially_parameterized_over_tcx {
+    ($($ty:ty),+ $(,)?) => {
+        $(
+            impl $crate::ty::ParameterizedOverTcx for $ty {
+                #[allow(unused_lifetimes)]
+                type Value<'tcx> = $ty;
+            }
+        )*
+    }
+}
+
+trivially_parameterized_over_tcx! {
+    usize,
+    (),
+    u32,
+    std::string::String,
+    crate::metadata::ModChild,
+    crate::middle::codegen_fn_attrs::CodegenFnAttrs,
+    crate::middle::exported_symbols::SymbolExportInfo,
+    crate::mir::ConstQualifs,
+    ty::Generics,
+    ty::ImplPolarity,
+    ty::ReprOptions,
+    ty::TraitDef,
+    ty::Visibility,
+    ty::adjustment::CoerceUnsizedInfo,
+    ty::fast_reject::SimplifiedTypeGen<DefId>,
+    rustc_ast::Attribute,
+    rustc_ast::MacArgs,
+    rustc_attr::ConstStability,
+    rustc_attr::Deprecation,
+    rustc_attr::Stability,
+    rustc_hir::Constness,
+    rustc_hir::Defaultness,
+    rustc_hir::GeneratorKind,
+    rustc_hir::IsAsync,
+    rustc_hir::LangItem,
+    rustc_hir::def::DefKind,
+    rustc_hir::def_id::DefIndex,
+    rustc_hir::definitions::DefKey,
+    rustc_index::bit_set::FiniteBitSet<u32>,
+    rustc_session::cstore::ForeignModule,
+    rustc_session::cstore::LinkagePreference,
+    rustc_session::cstore::NativeLib,
+    rustc_span::DebuggerVisualizerFile,
+    rustc_span::ExpnData,
+    rustc_span::ExpnHash,
+    rustc_span::ExpnId,
+    rustc_span::SourceFile,
+    rustc_span::Span,
+    rustc_span::Symbol,
+    rustc_span::def_id::DefPathHash,
+    rustc_span::hygiene::SyntaxContextData,
+    rustc_span::symbol::Ident,
+    rustc_type_ir::Variance,
+}
+
+// HACK(compiler-errors): This macro rule can only take an ident,
+// not a path, due to parsing ambiguity reasons. That means we gotta
+// import all of these types above.
+#[macro_export]
+macro_rules! parameterized_over_tcx {
+    ($($ident:ident),+ $(,)?) => {
+        $(
+            impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
+                type Value<'tcx> = $ident<'tcx>;
+            }
+        )*
+    }
+}
+
+parameterized_over_tcx! {
+    Ty,
+    FnSig,
+    GenericPredicates,
+    TraitRef,
+    Const,
+    Predicate,
+    GeneratorDiagnosticData,
+    Body,
+    Node,
+    ExportedSymbol,
+}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 0fd67f1..0a0c765 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -52,11 +52,20 @@
                 })
             }
             ExprKind::Repeat { value, count } => {
-                let value_operand = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[value], None, NeedsTemporary::No)
-                );
-                block.and(Rvalue::Repeat(value_operand, count))
+                if Some(0) == count.try_eval_usize(this.tcx, this.param_env) {
+                    this.build_zero_repeat(block, value, scope, source_info)
+                } else {
+                    let value_operand = unpack!(
+                        block = this.as_operand(
+                            block,
+                            scope,
+                            &this.thir[value],
+                            None,
+                            NeedsTemporary::No
+                        )
+                    );
+                    block.and(Rvalue::Repeat(value_operand, count))
+                }
             }
             ExprKind::Binary { op, lhs, rhs } => {
                 let lhs = unpack!(
@@ -141,7 +150,8 @@
                     TerminatorKind::Call {
                         func: exchange_malloc,
                         args: vec![Operand::Move(size), Operand::Move(align)],
-                        destination: Some((storage, success)),
+                        destination: storage,
+                        target: Some(success),
                         cleanup: None,
                         from_hir_call: false,
                         fn_span: expr_span,
@@ -515,6 +525,37 @@
         }
     }
 
+    fn build_zero_repeat(
+        &mut self,
+        mut block: BasicBlock,
+        value: ExprId,
+        scope: Option<region::Scope>,
+        outer_source_info: SourceInfo,
+    ) -> BlockAnd<Rvalue<'tcx>> {
+        let this = self;
+        let value = &this.thir[value];
+        let elem_ty = value.ty;
+        if let Some(Category::Constant) = Category::of(&value.kind) {
+            // Repeating a const does nothing
+        } else {
+            // For a non-const, we may need to generate an appropriate `Drop`
+            let value_operand =
+                unpack!(block = this.as_operand(block, scope, value, None, NeedsTemporary::No));
+            if let Operand::Move(to_drop) = value_operand {
+                let success = this.cfg.start_new_block();
+                this.cfg.terminate(
+                    block,
+                    outer_source_info,
+                    TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+                );
+                this.diverge_from(block);
+                block = success;
+            }
+            this.record_operands_moved(&[value_operand]);
+        }
+        block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), Vec::new()))
+    }
+
     fn limit_capture_mutability(
         &mut self,
         upvar_span: Span,
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index e912501..569012e 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -255,18 +255,19 @@
                         func: fun,
                         args,
                         cleanup: None,
+                        destination,
                         // The presence or absence of a return edge affects control-flow sensitive
                         // MIR checks and ultimately whether code is accepted or not. We can only
                         // omit the return edge if a return type is visibly uninhabited to a module
                         // that makes the call.
-                        destination: if this.tcx.is_ty_uninhabited_from(
+                        target: if this.tcx.is_ty_uninhabited_from(
                             this.parent_module,
                             expr.ty,
                             this.param_env,
                         ) {
                             None
                         } else {
-                            Some((destination, success))
+                            Some(success)
                         },
                         from_hir_call,
                         fn_span,
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 5653455..c15b3db 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -444,7 +444,8 @@
                     literal: method,
                 })),
                 args: vec![val, expect],
-                destination: Some((eq_result, eq_block)),
+                destination: eq_result,
+                target: Some(eq_block),
                 cleanup: None,
                 from_hir_call: false,
                 fn_span: source_info.span,
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 53f9706..a5f8a58 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1033,6 +1033,7 @@
                 self.cfg.block_data(start).terminator().kind,
                 TerminatorKind::Assert { .. }
                     | TerminatorKind::Call { .. }
+                    | TerminatorKind::Drop { .. }
                     | TerminatorKind::DropAndReplace { .. }
                     | TerminatorKind::FalseUnwind { .. }
                     | TerminatorKind::InlineAsm { .. }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 880f86a..f694e00 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -121,27 +121,27 @@
 
     fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
         traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
-            with_no_trimmed_paths!(match non_sm_ty {
-                traits::NonStructuralMatchTy::Adt(adt) => self.adt_derive_msg(adt),
-                traits::NonStructuralMatchTy::Dynamic => {
+            with_no_trimmed_paths!(match non_sm_ty.kind {
+                traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
+                traits::NonStructuralMatchTyKind::Dynamic => {
                     "trait objects cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Opaque => {
+                traits::NonStructuralMatchTyKind::Opaque => {
                     "opaque types cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Closure => {
+                traits::NonStructuralMatchTyKind::Closure => {
                     "closures cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Generator => {
+                traits::NonStructuralMatchTyKind::Generator => {
                     "generators cannot be used in patterns".to_string()
                 }
-                traits::NonStructuralMatchTy::Param => {
+                traits::NonStructuralMatchTyKind::Param => {
                     bug!("use of a constant whose type is a parameter inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Projection => {
+                traits::NonStructuralMatchTyKind::Projection => {
                     bug!("use of a constant whose type is a projection inside a pattern")
                 }
-                traits::NonStructuralMatchTy::Foreign => {
+                traits::NonStructuralMatchTyKind::Foreign => {
                     bug!("use of a value of a foreign type inside a pattern")
                 }
             })
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index f568121..027af5b 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -625,7 +625,8 @@
                 kind: TerminatorKind::Call {
                     func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span),
                     args: vec![Operand::Move(Place::from(ref_place))],
-                    destination: Some((unit_temp, succ)),
+                    destination: unit_temp,
+                    target: Some(succ),
                     cleanup: unwind.into_option(),
                     from_hir_call: true,
                     fn_span: self.source_info.span,
@@ -963,7 +964,8 @@
         let call = TerminatorKind::Call {
             func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
             args,
-            destination: Some((unit_temp, target)),
+            destination: unit_temp,
+            target: Some(target),
             cleanup: None,
             from_hir_call: false,
             fn_span: self.source_info.span,
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index d6bfde8..3a492b4 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -237,14 +237,12 @@
                 // Apply terminator-specific edge effects.
                 //
                 // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
-                mir::TerminatorKind::Call { destination: Some((return_place, dest)), .. }
-                    if dest == bb =>
-                {
+                mir::TerminatorKind::Call { destination, target: Some(dest), .. } if dest == bb => {
                     let mut tmp = exit_state.clone();
                     analysis.apply_call_return_effect(
                         &mut tmp,
                         pred,
-                        CallReturnPlaces::Call(return_place),
+                        CallReturnPlaces::Call(destination),
                     );
                     propagate(pred, &tmp);
                 }
@@ -532,20 +530,28 @@
                 propagate(target, exit_state);
             }
 
-            Call { cleanup, destination, func: _, args: _, from_hir_call: _, fn_span: _ } => {
+            Call {
+                cleanup,
+                destination,
+                target,
+                func: _,
+                args: _,
+                from_hir_call: _,
+                fn_span: _,
+            } => {
                 if let Some(unwind) = cleanup {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
                         propagate(unwind, exit_state);
                     }
                 }
 
-                if let Some((dest_place, target)) = destination {
+                if let Some(target) = target {
                     // N.B.: This must be done *last*, otherwise the unwind path will see the call
                     // return effect.
                     analysis.apply_call_return_effect(
                         exit_state,
                         bb,
-                        CallReturnPlaces::Call(dest_place),
+                        CallReturnPlaces::Call(destination),
                     );
                     propagate(target, exit_state);
                 }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index c6a85bc..3834c23 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -218,7 +218,7 @@
         self.results.seek_to_block_end(block);
         if self.results.get() != &block_start_state || A::Direction::is_backward() {
             let after_terminator_name = match terminator.kind {
-                mir::TerminatorKind::Call { destination: Some(_), .. } => "(on unwind)",
+                mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
                 _ => "(on end)",
             };
 
@@ -231,14 +231,14 @@
         // for the basic block itself. That way, we could display terminator-specific effects for
         // backward dataflow analyses as well as effects for `SwitchInt` terminators.
         match terminator.kind {
-            mir::TerminatorKind::Call { destination: Some((return_place, _)), .. } => {
+            mir::TerminatorKind::Call { destination, .. } => {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
                     let state_on_unwind = this.results.get().clone();
                     this.results.apply_custom_effect(|analysis, state| {
                         analysis.apply_call_return_effect(
                             state,
                             block,
-                            CallReturnPlaces::Call(return_place),
+                            CallReturnPlaces::Call(destination),
                         );
                     });
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 708a142..74c3b44 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -37,7 +37,8 @@
         mir::TerminatorKind::Call {
             func: mir::Operand::Copy(dummy_place.clone()),
             args: vec![],
-            destination: Some((dummy_place.clone(), mir::START_BLOCK)),
+            destination: dummy_place.clone(),
+            target: Some(mir::START_BLOCK),
             cleanup: None,
             from_hir_call: false,
             fn_span: DUMMY_SP,
@@ -50,7 +51,8 @@
         mir::TerminatorKind::Call {
             func: mir::Operand::Copy(dummy_place.clone()),
             args: vec![],
-            destination: Some((dummy_place.clone(), mir::START_BLOCK)),
+            destination: dummy_place.clone(),
+            target: Some(mir::START_BLOCK),
             cleanup: None,
             from_hir_call: false,
             fn_span: DUMMY_SP,
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 2730e8bd..356a6b7 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -169,8 +169,8 @@
         self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc);
 
         match &terminator.kind {
-            TerminatorKind::Call { destination: Some((place, _)), .. } => {
-                trans.gen(place.local);
+            TerminatorKind::Call { destination, .. } => {
+                trans.gen(destination.local);
             }
 
             // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
@@ -198,8 +198,7 @@
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Call { destination: None, .. }
-            | TerminatorKind::Abort
+            TerminatorKind::Abort
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::DropAndReplace { .. }
@@ -225,8 +224,8 @@
             // and after the call returns successfully, but not after a panic.
             // Since `propagate_call_unwind` doesn't exist, we have to kill the
             // destination here, and then gen it again in `call_return_effect`.
-            TerminatorKind::Call { destination: Some((place, _)), .. } => {
-                trans.kill(place.local);
+            TerminatorKind::Call { destination, .. } => {
+                trans.kill(destination.local);
             }
 
             // The same applies to InlineAsm outputs.
@@ -236,8 +235,7 @@
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Call { destination: None, .. }
-            | TerminatorKind::Yield { .. }
+            TerminatorKind::Yield { .. }
             | TerminatorKind::Abort
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 7307246..b08cb50 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -376,7 +376,8 @@
             TerminatorKind::Call {
                 ref func,
                 ref args,
-                ref destination,
+                destination,
+                target,
                 cleanup: _,
                 from_hir_call: _,
                 fn_span: _,
@@ -385,7 +386,7 @@
                 for arg in args {
                     self.gather_operand(arg);
                 }
-                if let Some((destination, _bb)) = *destination {
+                if let Some(_bb) = target {
                     self.create_move_path(destination);
                     self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
                 }
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index cd6b671..10d5227 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -50,12 +50,7 @@
         for block in body.basic_blocks_mut() {
             match block.terminator {
                 Some(Terminator {
-                    kind:
-                        TerminatorKind::Call {
-                            destination: Some((_, ref mut destination)),
-                            cleanup,
-                            ..
-                        },
+                    kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. },
                     source_info,
                 }) if pred_count[*destination] > 1
                     && (cleanup.is_some() || self == &AllCallEdges) =>
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index a245da6..0495439 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -130,11 +130,11 @@
             .iter_mut()
             .filter_map(|block_data| {
                 match block_data.terminator().kind {
-                    TerminatorKind::Call { destination: Some(ref destination), .. }
-                        if needs_retag(&destination.0) =>
+                    TerminatorKind::Call { target: Some(target), destination, .. }
+                        if needs_retag(&destination) =>
                     {
                         // Remember the return destination for later
-                        Some((block_data.terminator().source_info, destination.0, destination.1))
+                        Some((block_data.terminator().source_info, destination, target))
                     }
 
                     // `Drop` is also a call, but it doesn't return anything so we are good.
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 54c3cc4..b17485f 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -200,7 +200,8 @@
         _instance: ty::Instance<'tcx>,
         _abi: Abi,
         _args: &[OpTy<'tcx>],
-        _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
+        _destination: &PlaceTy<'tcx>,
+        _target: Option<BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         Ok(None)
@@ -210,7 +211,8 @@
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _args: &[OpTy<'tcx>],
-        _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
+        _destination: &PlaceTy<'tcx>,
+        _target: Option<BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<'tcx> {
         throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
@@ -384,24 +386,22 @@
             ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
         );
 
-        let ret = ecx
+        let ret_layout = ecx
             .layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
             .ok()
-            // Don't bother allocating memory for ZST types which have no values
-            // or for large values.
-            .filter(|ret_layout| {
-                !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
-            })
-            .map(|ret_layout| {
-                ecx.allocate(ret_layout, MemoryKind::Stack)
-                    .expect("couldn't perform small allocation")
-                    .into()
-            });
+            // Don't bother allocating memory for large values.
+            .filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT))
+            .unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap());
+
+        let ret = ecx
+            .allocate(ret_layout, MemoryKind::Stack)
+            .expect("couldn't perform small allocation")
+            .into();
 
         ecx.push_stack_frame(
             Instance::new(def_id, substs),
             dummy_body,
-            ret.as_ref(),
+            &ret,
             StackPopCleanup::Root { cleanup: false },
         )
         .expect("failed to push initial stack frame");
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 6c0df98..5fd9db3 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -192,7 +192,8 @@
         _instance: ty::Instance<'tcx>,
         _abi: Abi,
         _args: &[OpTy<'tcx>],
-        _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
+        _destination: &PlaceTy<'tcx>,
+        _target: Option<BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         Ok(None)
@@ -202,7 +203,8 @@
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _args: &[OpTy<'tcx>],
-        _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>,
+        _destination: &PlaceTy<'tcx>,
+        _target: Option<BasicBlock>,
         _unwind: StackPopUnwind,
     ) -> InterpResult<'tcx> {
         throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
@@ -377,24 +379,22 @@
             ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
         );
 
-        let ret = ecx
+        let ret_layout = ecx
             .layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
             .ok()
-            // Don't bother allocating memory for ZST types which have no values
-            // or for large values.
-            .filter(|ret_layout| {
-                !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
-            })
-            .map(|ret_layout| {
-                ecx.allocate(ret_layout, MemoryKind::Stack)
-                    .expect("couldn't perform small allocation")
-                    .into()
-            });
+            // Don't bother allocating memory for large values.
+            .filter(|ret_layout| ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT))
+            .unwrap_or_else(|| ecx.layout_of(tcx.types.unit).unwrap());
+
+        let ret = ecx
+            .allocate(ret_layout, MemoryKind::Stack)
+            .expect("couldn't perform small allocation")
+            .into();
 
         ecx.push_stack_frame(
             Instance::new(def_id, substs),
             dummy_body,
-            ret.as_ref(),
+            &ret,
             StackPopCleanup::Root { cleanup: false },
         )
         .expect("failed to push initial stack frame");
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index d787443..4615f9b 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -84,7 +84,7 @@
     fn link(&mut self, from_block: BasicBlock, to_block: BasicBlock) {
         match self.blocks[from_block].terminator_mut().kind {
             TerminatorKind::Assert { ref mut target, .. }
-            | TerminatorKind::Call { destination: Some((_, ref mut target)), .. }
+            | TerminatorKind::Call { target: Some(ref mut target), .. }
             | TerminatorKind::Drop { ref mut target, .. }
             | TerminatorKind::DropAndReplace { ref mut target, .. }
             | TerminatorKind::FalseEdge { real_target: ref mut target, .. }
@@ -139,7 +139,8 @@
             TerminatorKind::Call {
                 func: Operand::Copy(self.dummy_place.clone()),
                 args: vec![],
-                destination: Some((self.dummy_place.clone(), TEMP_BLOCK)),
+                destination: self.dummy_place.clone(),
+                target: Some(TEMP_BLOCK),
                 cleanup: None,
                 from_hir_call: false,
                 fn_span: DUMMY_SP,
@@ -182,7 +183,7 @@
                 let sp = format!("(span:{},{})", span.lo().to_u32(), span.hi().to_u32());
                 match kind {
                     TerminatorKind::Assert { target, .. }
-                    | TerminatorKind::Call { destination: Some((_, target)), .. }
+                    | TerminatorKind::Call { target: Some(target), .. }
                     | TerminatorKind::Drop { target, .. }
                     | TerminatorKind::DropAndReplace { target, .. }
                     | TerminatorKind::FalseEdge { real_target: target, .. }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 3732a30..182dd6f 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -575,7 +575,8 @@
             TerminatorKind::Call {
                 func,
                 args,
-                destination: Some((dest_place, _)),
+                destination,
+                target: _,
                 cleanup: _,
                 from_hir_call: _,
                 fn_span: _,
@@ -583,9 +584,9 @@
                 // No arguments may overlap with the destination.
                 for arg in args.iter().chain(Some(func)) {
                     if let Some(place) = arg.place() {
-                        if !place.is_indirect() && !dest_place.is_indirect() {
+                        if !place.is_indirect() && !destination.is_indirect() {
                             self.record_local_conflict(
-                                dest_place.local,
+                                destination.local,
                                 place.local,
                                 "call dest/arg overlap",
                             );
@@ -691,7 +692,6 @@
             }
 
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Call { destination: None, .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
             | TerminatorKind::Abort
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index f78c7a0..8a9f210 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -494,15 +494,13 @@
     fn drop_flags_for_fn_rets(&mut self) {
         for (bb, data) in self.body.basic_blocks().iter_enumerated() {
             if let TerminatorKind::Call {
-                destination: Some((ref place, tgt)),
-                cleanup: Some(_),
-                ..
+                destination, target: Some(tgt), cleanup: Some(_), ..
             } = data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: tgt, statement_index: 0 };
-                let path = self.move_data().rev_lookup.find(place.as_ref());
+                let path = self.move_data().rev_lookup.find(destination.as_ref());
                 on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
                     self.set_drop_flag(loc, child, DropFlagState::Present)
                 });
@@ -576,14 +574,13 @@
             // There may be a critical edge after this call,
             // so mark the return as initialized *before* the
             // call.
-            if let TerminatorKind::Call {
-                destination: Some((ref place, _)), cleanup: None, ..
-            } = data.terminator().kind
+            if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } =
+                data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
 
                 let loc = Location { block: bb, statement_index: data.statements.len() };
-                let path = self.move_data().rev_lookup.find(place.as_ref());
+                let path = self.move_data().rev_lookup.find(destination.as_ref());
                 on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
                     self.set_drop_flag(loc, child, DropFlagState::Present)
                 });
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 1f9bd90..2e4fe1e 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -37,6 +37,7 @@
             func,
             args,
             destination: _,
+            target: _,
             cleanup: _,
             from_hir_call: _,
             fn_span: _,
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 9e7bf5c..4a3505c 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1459,12 +1459,13 @@
             TerminatorKind::Call {
                 func,
                 args,
-                destination: Some((dest, _)),
+                destination,
+                target: Some(_),
                 cleanup: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
-                self.check_assigned_place(*dest, |this| {
+                self.check_assigned_place(*destination, |this| {
                     this.visit_operand(func, location);
                     for arg in args {
                         this.visit_operand(arg, location);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 017d9e7..66fb01b 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -248,7 +248,7 @@
     ) -> Option<CallSite<'tcx>> {
         // Only consider direct calls to functions
         let terminator = bb_data.terminator();
-        if let TerminatorKind::Call { ref func, ref destination, .. } = terminator.kind {
+        if let TerminatorKind::Call { ref func, target, .. } = terminator.kind {
             let func_ty = func.ty(caller_body, self.tcx);
             if let ty::FnDef(def_id, substs) = *func_ty.kind() {
                 // To resolve an instance its substs have to be fully normalized.
@@ -266,7 +266,7 @@
                     callee,
                     fn_sig,
                     block: bb,
-                    target: destination.map(|(_, target)| target),
+                    target,
                     source_info: terminator.source_info,
                 });
             }
@@ -395,7 +395,7 @@
                     }
                 }
 
-                TerminatorKind::Unreachable | TerminatorKind::Call { destination: None, .. }
+                TerminatorKind::Unreachable | TerminatorKind::Call { target: None, .. }
                     if first_block =>
                 {
                     // If the function always diverges, don't inline
@@ -512,27 +512,22 @@
                     false
                 }
 
-                let dest = if let Some((destination_place, _)) = destination {
-                    if dest_needs_borrow(destination_place) {
-                        trace!("creating temp for return destination");
-                        let dest = Rvalue::Ref(
-                            self.tcx.lifetimes.re_erased,
-                            BorrowKind::Mut { allow_two_phase_borrow: false },
-                            destination_place,
-                        );
-                        let dest_ty = dest.ty(caller_body, self.tcx);
-                        let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty));
-                        caller_body[callsite.block].statements.push(Statement {
-                            source_info: callsite.source_info,
-                            kind: StatementKind::Assign(Box::new((temp, dest))),
-                        });
-                        self.tcx.mk_place_deref(temp)
-                    } else {
-                        destination_place
-                    }
+                let dest = if dest_needs_borrow(destination) {
+                    trace!("creating temp for return destination");
+                    let dest = Rvalue::Ref(
+                        self.tcx.lifetimes.re_erased,
+                        BorrowKind::Mut { allow_two_phase_borrow: false },
+                        destination,
+                    );
+                    let dest_ty = dest.ty(caller_body, self.tcx);
+                    let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty));
+                    caller_body[callsite.block].statements.push(Statement {
+                        source_info: callsite.source_info,
+                        kind: StatementKind::Assign(Box::new((temp, dest))),
+                    });
+                    self.tcx.mk_place_deref(temp)
                 } else {
-                    trace!("creating temp for return place");
-                    Place::from(self.new_call_temp(caller_body, &callsite, callee_body.return_ty()))
+                    destination
                 };
 
                 // Copy the arguments if needed.
@@ -914,8 +909,8 @@
                     *unwind = self.cleanup_block;
                 }
             }
-            TerminatorKind::Call { ref mut destination, ref mut cleanup, .. } => {
-                if let Some((_, ref mut tgt)) = *destination {
+            TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
+                if let Some(ref mut tgt) = *target {
                     *tgt = self.map_block(*tgt);
                 }
                 if let Some(tgt) = *cleanup {
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 268ce1b..4fbb764 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -141,7 +141,7 @@
         terminator: &mut Terminator<'tcx>,
         statements: &mut Vec<Statement<'tcx>>,
     ) {
-        let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind
+        let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind
         else { return };
 
         // It's definitely not a clone if there are multiple arguments
@@ -149,7 +149,7 @@
             return;
         }
 
-        let Some((destination_place, destination_block)) = *destination
+        let Some(destination_block) = *target
         else { return };
 
         // Only bother looking more if it's easy to know what we're calling
@@ -193,7 +193,7 @@
         statements.push(Statement {
             source_info: terminator.source_info,
             kind: StatementKind::Assign(Box::new((
-                destination_place,
+                *destination,
                 Rvalue::Use(Operand::Copy(
                     arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx),
                 )),
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index d0d0e09..6580106 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -14,7 +14,9 @@
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for block in basic_blocks {
             let terminator = block.terminator.as_mut().unwrap();
-            if let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind {
+            if let TerminatorKind::Call { func, args, destination, target, .. } =
+                &mut terminator.kind
+            {
                 let func_ty = func.ty(local_decls, tcx);
                 let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(tcx, func_ty) else {
                     continue;
@@ -24,11 +26,11 @@
                         terminator.kind = TerminatorKind::Unreachable;
                     }
                     sym::forget => {
-                        if let Some((destination, target)) = *destination {
+                        if let Some(target) = *target {
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
-                                    destination,
+                                    *destination,
                                     Rvalue::Use(Operand::Constant(Box::new(Constant {
                                         span: terminator.source_info.span,
                                         user_ty: None,
@@ -40,7 +42,7 @@
                         }
                     }
                     sym::copy_nonoverlapping => {
-                        let target = destination.unwrap().1;
+                        let target = target.unwrap();
                         let mut args = args.drain(..);
                         block.statements.push(Statement {
                             source_info: terminator.source_info,
@@ -61,7 +63,7 @@
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
-                        if let Some((destination, target)) = *destination {
+                        if let Some(target) = *target {
                             let lhs;
                             let rhs;
                             {
@@ -78,7 +80,7 @@
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
-                                    destination,
+                                    *destination,
                                     Rvalue::BinaryOp(bin_op, Box::new((lhs, rhs))),
                                 ))),
                             });
@@ -91,7 +93,7 @@
                         // during codegen. Issue #35310.
                     }
                     sym::size_of | sym::min_align_of => {
-                        if let Some((destination, target)) = *destination {
+                        if let Some(target) = *target {
                             let tp_ty = substs.type_at(0);
                             let null_op = match intrinsic_name {
                                 sym::size_of => NullOp::SizeOf,
@@ -101,7 +103,7 @@
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
-                                    destination,
+                                    *destination,
                                     Rvalue::NullaryOp(null_op, tp_ty),
                                 ))),
                             });
@@ -109,14 +111,12 @@
                         }
                     }
                     sym::discriminant_value => {
-                        if let (Some((destination, target)), Some(arg)) =
-                            (*destination, args[0].place())
-                        {
+                        if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let arg = tcx.mk_place_deref(arg);
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
-                                    destination,
+                                    *destination,
                                     Rvalue::Discriminant(arg),
                                 ))),
                             });
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 43d1d62..07163cf 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -52,7 +52,8 @@
         TerminatorKind::Call {
             func,
             args,
-            destination: Some((dest, bb)),
+            destination,
+            target: Some(bb),
             cleanup: None,
             from_hir_call: true,
             ..
@@ -73,7 +74,8 @@
                     // make new RValue for Len
                     let deref_arg = tcx.mk_place_deref(arg);
                     let r_value = Rvalue::Len(deref_arg);
-                    let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
+                    let len_statement_kind =
+                        StatementKind::Assign(Box::new((*destination, r_value)));
                     let add_statement =
                         Statement { kind: len_statement_kind, source_info: terminator.source_info };
 
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 016b3bc..78a4ece 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -450,7 +450,8 @@
             TerminatorKind::Call {
                 func,
                 args: vec![Operand::Move(ref_loc)],
-                destination: Some((dest, next)),
+                destination: dest,
+                target: Some(next),
                 cleanup: Some(cleanup),
                 from_hir_call: true,
                 fn_span: self.span,
@@ -676,7 +677,8 @@
         TerminatorKind::Call {
             func: callee,
             args,
-            destination: Some((Place::return_place(), BasicBlock::new(1))),
+            destination: Place::return_place(),
+            target: Some(BasicBlock::new(1)),
             cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
                 Some(BasicBlock::new(3))
             } else {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index ee02151..a9ca892 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -201,7 +201,6 @@
 use rustc_session::Limit;
 use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
 use rustc_target::abi::Size;
-use smallvec::SmallVec;
 use std::iter;
 use std::ops::Range;
 use std::path::PathBuf;
@@ -226,6 +225,44 @@
     inlines: GrowableBitSet<usize>,
 }
 
+/// Struct to store mono items in each collecting and if they should
+/// be inlined. We call `instantiation_mode` to get their inlining
+/// status when inserting new elements, which avoids calling it in
+/// `inlining_map.lock_mut()`. See the `collect_items_rec` implementation
+/// below.
+struct MonoItems<'tcx> {
+    // If this is false, we do not need to compute whether items
+    // will need to be inlined.
+    compute_inlining: bool,
+
+    // The TyCtxt used to determine whether the a item should
+    // be inlined.
+    tcx: TyCtxt<'tcx>,
+
+    // The collected mono items. The bool field in each element
+    // indicates whether this element should be inlined.
+    items: Vec<(Spanned<MonoItem<'tcx>>, bool /*inlined*/)>,
+}
+
+impl<'tcx> MonoItems<'tcx> {
+    #[inline]
+    fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
+        self.extend([item]);
+    }
+
+    #[inline]
+    fn extend<T: IntoIterator<Item = Spanned<MonoItem<'tcx>>>>(&mut self, iter: T) {
+        self.items.extend(iter.into_iter().map(|mono_item| {
+            let inlined = if !self.compute_inlining {
+                false
+            } else {
+                mono_item.node.instantiation_mode(self.tcx) == InstantiationMode::LocalCopy
+            };
+            (mono_item, inlined)
+        }))
+    }
+}
+
 impl<'tcx> InliningMap<'tcx> {
     fn new() -> InliningMap<'tcx> {
         InliningMap {
@@ -235,7 +272,13 @@
         }
     }
 
-    fn record_accesses(&mut self, source: MonoItem<'tcx>, new_targets: &[(MonoItem<'tcx>, bool)]) {
+    fn record_accesses<'a>(
+        &mut self,
+        source: MonoItem<'tcx>,
+        new_targets: &'a [(Spanned<MonoItem<'tcx>>, bool)],
+    ) where
+        'tcx: 'a,
+    {
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
         let new_items_count_total = new_items_count + self.targets.len();
@@ -243,9 +286,9 @@
         self.targets.reserve(new_items_count);
         self.inlines.ensure(new_items_count_total);
 
-        for (i, (target, inline)) in new_targets.iter().enumerate() {
-            self.targets.push(*target);
-            if *inline {
+        for (i, (Spanned { node: mono_item, .. }, inlined)) in new_targets.into_iter().enumerate() {
+            self.targets.push(*mono_item);
+            if *inlined {
                 self.inlines.insert(i + start_index);
             }
         }
@@ -321,7 +364,7 @@
 // start monomorphizing from.
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("collecting roots");
-    let mut roots = Vec::new();
+    let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
 
     {
         let entry_fn = tcx.entry_fn(());
@@ -347,8 +390,11 @@
     // whose predicates hold. Luckily, items that aren't instantiable
     // can't actually be used, so we can just skip codegenning them.
     roots
+        .items
         .into_iter()
-        .filter_map(|root| root.node.is_instantiable(tcx).then_some(root.node))
+        .filter_map(|(Spanned { node: mono_item, .. }, _)| {
+            mono_item.is_instantiable(tcx).then_some(mono_item)
+        })
         .collect()
 }
 
@@ -368,7 +414,7 @@
     }
     debug!("BEGIN collect_items_rec({})", starting_point.node);
 
-    let mut neighbors = Vec::new();
+    let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
     let recursion_depth_reset;
 
     //
@@ -483,10 +529,9 @@
             &format!("the above error was encountered while instantiating `{}`", formatted_item),
         );
     }
+    inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
 
-    record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
-
-    for neighbour in neighbors {
+    for (neighbour, _) in neighbors.items {
         collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
     }
 
@@ -497,25 +542,6 @@
     debug!("END collect_items_rec({})", starting_point.node);
 }
 
-fn record_accesses<'a, 'tcx: 'a>(
-    tcx: TyCtxt<'tcx>,
-    caller: MonoItem<'tcx>,
-    callees: impl Iterator<Item = &'a MonoItem<'tcx>>,
-    inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
-) {
-    let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| {
-        mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
-    };
-
-    // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock.
-    // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec`
-    // instead to avoid creating this `SmallVec`.
-    let accesses: SmallVec<[_; 128]> =
-        callees.map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect();
-
-    inlining_map.lock_mut().record_accesses(caller, &accesses);
-}
-
 /// Format instance name that is already known to be too long for rustc.
 /// Show only the first and last 32 characters to avoid blasting
 /// the user's terminal with thousands of lines of type-name.
@@ -627,7 +653,7 @@
 struct MirNeighborCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     body: &'a mir::Body<'tcx>,
-    output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &'a mut MonoItems<'tcx>,
     instance: Instance<'tcx>,
 }
 
@@ -905,7 +931,7 @@
     ty: Ty<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     let instance = Instance::resolve_drop_in_place(tcx, ty);
     visit_instance_use(tcx, instance, is_direct_call, source, output);
@@ -916,7 +942,7 @@
     ty: Ty<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     if let ty::FnDef(def_id, substs) = *ty.kind() {
         let instance = if is_direct_call {
@@ -934,7 +960,7 @@
     instance: ty::Instance<'tcx>,
     is_direct_call: bool,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
     if !should_codegen_locally(tcx, &instance) {
@@ -1117,7 +1143,7 @@
     trait_ty: Ty<'tcx>,
     impl_ty: Ty<'tcx>,
     source: Span,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars());
 
@@ -1159,7 +1185,7 @@
 struct RootCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     mode: MonoItemCollectionMode,
-    output: &'a mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &'a mut MonoItems<'tcx>,
     entry_fn: Option<(DefId, EntryFnType)>,
 }
 
@@ -1305,7 +1331,7 @@
 fn create_mono_items_for_default_impls<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::Item<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     match item.kind {
         hir::ItemKind::Impl(ref impl_) => {
@@ -1361,11 +1387,7 @@
 }
 
 /// Scans the miri alloc in order to find function calls, closures, and drop-glue.
-fn collect_miri<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    alloc_id: AllocId,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
-) {
+fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoItems<'tcx>) {
     match tcx.global_alloc(alloc_id) {
         GlobalAlloc::Static(def_id) => {
             assert!(!tcx.is_thread_local_static(def_id));
@@ -1396,7 +1418,7 @@
 fn collect_neighbours<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     debug!("collect_neighbours: {:?}", instance.def_id());
     let body = tcx.instance_mir(instance.def);
@@ -1407,7 +1429,7 @@
 fn collect_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     value: ConstValue<'tcx>,
-    output: &mut Vec<Spanned<MonoItem<'tcx>>>,
+    output: &mut MonoItems<'tcx>,
 ) {
     match value {
         ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output),
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 69e1206..c9da58a 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -254,23 +254,23 @@
 
 #[derive(SessionDiagnostic)]
 #[error(code = "E0178", slug = "parser-maybe-recover-from-bad-type-plus")]
-struct BadTypePlus<'a> {
+struct BadTypePlus {
     pub ty: String,
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sub: BadTypePlusSub<'a>,
+    pub sub: BadTypePlusSub,
 }
 
-#[derive(SessionSubdiagnostic, Clone, Copy)]
-pub enum BadTypePlusSub<'a> {
+#[derive(SessionSubdiagnostic)]
+pub enum BadTypePlusSub {
     #[suggestion(
         slug = "parser-add-paren",
         code = "{sum_with_parens}",
         applicability = "machine-applicable"
     )]
     AddParen {
-        sum_with_parens: &'a str,
+        sum_with_parens: String,
         #[primary_span]
         span: Span,
     },
@@ -1289,11 +1289,9 @@
         let bounds = self.parse_generic_bounds(None)?;
         let sum_span = ty.span.to(self.prev_token.span);
 
-        let sum_with_parens: String;
-
         let sub = match ty.kind {
             TyKind::Rptr(ref lifetime, ref mut_ty) => {
-                sum_with_parens = pprust::to_string(|s| {
+                let sum_with_parens = pprust::to_string(|s| {
                     s.s.word("&");
                     s.print_opt_lifetime(lifetime);
                     s.print_mutability(mut_ty.mutbl, false);
@@ -1303,7 +1301,7 @@
                     s.pclose()
                 });
 
-                BadTypePlusSub::AddParen { sum_with_parens: &sum_with_parens, span: sum_span }
+                BadTypePlusSub::AddParen { sum_with_parens, span: sum_span }
             }
             TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span },
             _ => BadTypePlusSub::ExpectPath { span: sum_span },
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index b5467c6..bb6d892 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2010,6 +2010,12 @@
         Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
     }
 
+    /// Parse a block which takes no attributes and has no label
+    fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
+        let blk = self.parse_block()?;
+        Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
+    }
+
     /// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`.
     fn recover_quantified_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
@@ -2157,6 +2163,15 @@
         let lo = self.prev_token.span;
         let cond = self.parse_cond_expr()?;
 
+        self.parse_if_after_cond(attrs, lo, cond)
+    }
+
+    fn parse_if_after_cond(
+        &mut self,
+        attrs: AttrVec,
+        lo: Span,
+        cond: P<Expr>,
+    ) -> PResult<'a, P<Expr>> {
         let missing_then_block_binop_span = || {
             match cond.kind {
                 ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right)
@@ -2164,7 +2179,6 @@
                 _ => None
             }
         };
-
         // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
         // verify that the last statement is either an implicit return (no `;`) or an explicit
         // return. This won't catch blocks with an explicit `return`, but that would be caught by
@@ -2256,15 +2270,46 @@
 
     /// Parses an `else { ... }` expression (`else` token already eaten).
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
-        let ctx_span = self.prev_token.span; // `else`
+        let else_span = self.prev_token.span; // `else`
         let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
         let expr = if self.eat_keyword(kw::If) {
             self.parse_if_expr(AttrVec::new())?
+        } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
+            self.parse_simple_block()?
         } else {
-            let blk = self.parse_block()?;
-            self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())
+            let snapshot = self.create_snapshot_for_diagnostic();
+            let first_tok = super::token_descr(&self.token);
+            let first_tok_span = self.token.span;
+            match self.parse_expr() {
+                Ok(cond)
+                // If it's not a free-standing expression, and is followed by a block,
+                // then it's very likely the condition to an `else if`.
+                    if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
+                        && classify::expr_requires_semi_to_be_stmt(&cond) =>
+                {
+                    self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}"))
+                        .span_label(else_span, "expected an `if` or a block after this `else`")
+                        .span_suggestion(
+                            cond.span.shrink_to_lo(),
+                            "add an `if` if this is the condition of a chained `else if` statement",
+                            "if ".to_string(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    self.parse_if_after_cond(AttrVec::new(), cond.span.shrink_to_lo(), cond)?
+                }
+                Err(e) => {
+                    e.cancel();
+                    self.restore_snapshot(snapshot);
+                    self.parse_simple_block()?
+                },
+                Ok(_) => {
+                    self.restore_snapshot(snapshot);
+                    self.parse_simple_block()?
+                },
+            }
         };
-        self.error_on_if_block_attrs(ctx_span, true, expr.span, &attrs);
+        self.error_on_if_block_attrs(else_span, true, expr.span, &attrs);
         Ok(expr)
     }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 673b2e3..a6a04ac 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -445,6 +445,8 @@
                 );
             }
         }
+        // Try Levenshtein algorithm.
+        let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected);
         if path.len() == 1 && self.self_type_is_available() {
             if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) {
                 let self_is_available = self.self_value_is_available(path[0].ident.span);
@@ -454,7 +456,7 @@
                             err.span_suggestion(
                                 span,
                                 "you might have meant to use the available field",
-                                format!("self.{}", path_str),
+                                format!("self.{path_str}"),
                                 Applicability::MachineApplicable,
                             );
                         } else {
@@ -465,7 +467,7 @@
                         err.span_suggestion(
                             span,
                             "you might have meant to call the method",
-                            format!("self.{}", path_str),
+                            format!("self.{path_str}"),
                             Applicability::MachineApplicable,
                         );
                     }
@@ -476,11 +478,12 @@
                         err.span_suggestion(
                             span,
                             &format!("you might have meant to {}", candidate.action()),
-                            format!("Self::{}", path_str),
+                            format!("Self::{path_str}"),
                             Applicability::MachineApplicable,
                         );
                     }
                 }
+                self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
                 return (err, candidates);
             }
 
@@ -495,16 +498,14 @@
 
                 err.span_suggestion(
                     call_span,
-                    &format!("try calling `{}` as a method", ident),
-                    format!("self.{}({})", path_str, args_snippet),
+                    &format!("try calling `{ident}` as a method"),
+                    format!("self.{path_str}({args_snippet})"),
                     Applicability::MachineApplicable,
                 );
                 return (err, candidates);
             }
         }
 
-        // Try Levenshtein algorithm.
-        let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected);
         // Try context-dependent help if relaxed lookup didn't work.
         if let Some(res) = res {
             if self.smart_resolve_context_dependent_help(
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 12e00ef..66198df 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1495,6 +1495,8 @@
         "hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
     stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED],
         "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"),
+    strict_init_checks: bool = (false, parse_bool, [TRACKED],
+        "control if mem::uninitialized and mem::zeroed panic on more UB"),
     strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
         "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
     split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5c9c163..406e9a4 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -427,6 +427,7 @@
         cfg_panic,
         cfg_sanitize,
         cfg_target_abi,
+        cfg_target_compact,
         cfg_target_feature,
         cfg_target_has_atomic,
         cfg_target_has_atomic_equal_alignment,
@@ -1375,6 +1376,7 @@
         sym,
         sync,
         t32,
+        target,
         target_abi,
         target_arch,
         target_endian,
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index a2cd3c4..a771369 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -894,6 +894,15 @@
             Scalar::Union { .. } => true,
         }
     }
+
+    /// Returns `true` if this type can be left uninit.
+    #[inline]
+    pub fn is_uninit_valid(&self) -> bool {
+        match *self {
+            Scalar::Initialized { .. } => false,
+            Scalar::Union { .. } => true,
+        }
+    }
 }
 
 /// Describes how the fields of a type are located in memory.
@@ -1355,6 +1364,14 @@
     pub address_space: AddressSpace,
 }
 
+/// Used in `might_permit_raw_init` to indicate the kind of initialisation
+/// that is checked to be valid
+#[derive(Copy, Clone, Debug)]
+pub enum InitKind {
+    Zero,
+    Uninit,
+}
+
 /// Trait that needs to be implemented by the higher-level type representation
 /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
 pub trait TyAbiInterface<'a, C>: Sized {
@@ -1461,26 +1478,37 @@
 
     /// Determines if this type permits "raw" initialization by just transmuting some
     /// memory into an instance of `T`.
-    /// `zero` indicates if the memory is zero-initialized, or alternatively
-    /// left entirely uninitialized.
+    ///
+    /// `init_kind` indicates if the memory is zero-initialized or left uninitialized.
+    ///
+    /// `strict` is an opt-in debugging flag added in #97323 that enables more checks.
+    ///
     /// This is conservative: in doubt, it will answer `true`.
     ///
     /// FIXME: Once we removed all the conservatism, we could alternatively
     /// create an all-0/all-undef constant and run the const value validator to see if
     /// this is a valid value for the given type.
-    pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
+    pub fn might_permit_raw_init<C>(self, cx: &C, init_kind: InitKind, strict: bool) -> bool
     where
         Self: Copy,
         Ty: TyAbiInterface<'a, C>,
         C: HasDataLayout,
     {
         let scalar_allows_raw_init = move |s: Scalar| -> bool {
-            if zero {
-                // The range must contain 0.
-                s.valid_range(cx).contains(0)
-            } else {
-                // The range must include all values.
-                s.is_always_valid(cx)
+            match init_kind {
+                InitKind::Zero => {
+                    // The range must contain 0.
+                    s.valid_range(cx).contains(0)
+                }
+                InitKind::Uninit => {
+                    if strict {
+                        // The type must be allowed to be uninit (which means "is a union").
+                        s.is_uninit_valid()
+                    } else {
+                        // The range must include all values.
+                        s.is_always_valid(cx)
+                    }
+                }
             }
         };
 
@@ -1500,12 +1528,19 @@
         // If we have not found an error yet, we need to recursively descend into fields.
         match &self.fields {
             FieldsShape::Primitive | FieldsShape::Union { .. } => {}
-            FieldsShape::Array { .. } => {
-                // FIXME(#66151): For now, we are conservative and do not check arrays.
+            FieldsShape::Array { count, .. } => {
+                // FIXME(#66151): For now, we are conservative and do not check arrays by default.
+                if strict
+                    && *count > 0
+                    && !self.field(cx, 0).might_permit_raw_init(cx, init_kind, strict)
+                {
+                    // Found non empty array with a type that is unhappy about this kind of initialization
+                    return false;
+                }
             }
             FieldsShape::Arbitrary { offsets, .. } => {
                 for idx in 0..offsets.len() {
-                    if !self.field(cx, idx).might_permit_raw_init(cx, zero) {
+                    if !self.field(cx, idx).might_permit_raw_init(cx, init_kind, strict) {
                         // We found a field that is unhappy with this kind of initialization.
                         return false;
                     }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 832eeec..6dd245b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -108,6 +108,15 @@
 }
 
 impl LldFlavor {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            LldFlavor::Wasm => "wasm",
+            LldFlavor::Ld64 => "darwin",
+            LldFlavor::Ld => "gnu",
+            LldFlavor::Link => "link",
+        }
+    }
+
     fn from_str(s: &str) -> Option<Self> {
         Some(match s {
             "darwin" => LldFlavor::Ld64,
@@ -121,13 +130,7 @@
 
 impl ToJson for LldFlavor {
     fn to_json(&self) -> Json {
-        match *self {
-            LldFlavor::Ld64 => "darwin",
-            LldFlavor::Ld => "gnu",
-            LldFlavor::Link => "link",
-            LldFlavor::Wasm => "wasm",
-        }
-        .to_json()
+        self.as_str().to_json()
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index f46e8ff..539e949 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -20,6 +20,7 @@
 #![feature(label_break_value)]
 #![feature(let_chains)]
 #![feature(let_else)]
+#![feature(if_let_guard)]
 #![feature(never_type)]
 #![recursion_limit = "512"] // For rustdoc
 
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index a7893c0..e7f0e47 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -20,7 +20,7 @@
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::{util, TraitEngine};
 use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
@@ -79,26 +79,21 @@
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
+    let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
     let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
     let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
-
-    // Check if any of the input types definitely do not unify.
-    if iter::zip(
-        impl1_ref.iter().flat_map(|tref| tref.substs.types()),
-        impl2_ref.iter().flat_map(|tref| tref.substs.types()),
-    )
-    .any(|(ty1, ty2)| {
-        let t1 = fast_reject::simplify_type(tcx, ty1, TreatParams::AsInfer);
-        let t2 = fast_reject::simplify_type(tcx, ty2, TreatParams::AsInfer);
-
-        if let (Some(t1), Some(t2)) = (t1, t2) {
-            // Simplified successfully
-            t1 != t2
-        } else {
-            // Types might unify
-            false
+    let may_overlap = match (impl1_ref, impl2_ref) {
+        (Some(a), Some(b)) => iter::zip(a.substs, b.substs)
+            .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
+        (None, None) => {
+            let self_ty1 = tcx.type_of(impl1_def_id);
+            let self_ty2 = tcx.type_of(impl2_def_id);
+            drcx.types_may_unify(self_ty1, self_ty2)
         }
-    }) {
+        _ => bug!("unexpected impls: {impl1_def_id:?} {impl2_def_id:?}"),
+    };
+
+    if !may_overlap {
         // Some types involved are definitely different, so the impls couldn't possibly overlap.
         debug!("overlapping_impls: fast_reject early-exit");
         return no_overlap();
@@ -519,7 +514,7 @@
 /// 3. Before this local type, no generic type parameter of the impl must
 ///    be reachable through fundamental types.
 ///     - e.g. `impl<T> Trait<LocalType> for Vec<T>` is fine, as `Vec` is not fundamental.
-///     - while `impl<T> Trait<LocalType for Box<T>` results in an error, as `T` is
+///     - while `impl<T> Trait<LocalType> for Box<T>` results in an error, as `T` is
 ///       reachable through the fundamental type `Box`.
 /// 4. Every type in the local key parameter not known in C, going
 ///    through the parameter's type tree, must appear only as a subtree of
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 27ce08e..0dea2c3 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -39,150 +39,148 @@
     let tcx = infcx.tcx;
 
     if tcx.features().generic_const_exprs {
-        match AbstractConst::new(tcx, uv)? {
-            // We are looking at a generic abstract constant.
-            Some(ct) => {
-                if satisfied_from_param_env(tcx, ct, param_env)? {
-                    return Ok(());
-                }
-
-                // We were unable to unify the abstract constant with
-                // a constant found in the caller bounds, there are
-                // now three possible cases here.
-                #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-                enum FailureKind {
-                    /// The abstract const still references an inference
-                    /// variable, in this case we return `TooGeneric`.
-                    MentionsInfer,
-                    /// The abstract const references a generic parameter,
-                    /// this means that we emit an error here.
-                    MentionsParam,
-                    /// The substs are concrete enough that we can simply
-                    /// try and evaluate the given constant.
-                    Concrete,
-                }
-                let mut failure_kind = FailureKind::Concrete;
-                walk_abstract_const::<!, _>(tcx, ct, |node| match node.root(tcx) {
-                    Node::Leaf(leaf) => {
-                        if leaf.has_infer_types_or_consts() {
-                            failure_kind = FailureKind::MentionsInfer;
-                        } else if leaf.has_param_types_or_consts() {
-                            failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
-                        }
-
-                        ControlFlow::CONTINUE
-                    }
-                    Node::Cast(_, _, ty) => {
-                        if ty.has_infer_types_or_consts() {
-                            failure_kind = FailureKind::MentionsInfer;
-                        } else if ty.has_param_types_or_consts() {
-                            failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
-                        }
-
-                        ControlFlow::CONTINUE
-                    }
-                    Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
-                        ControlFlow::CONTINUE
-                    }
-                });
-
-                match failure_kind {
-                    FailureKind::MentionsInfer => {
-                        return Err(NotConstEvaluatable::MentionsInfer);
-                    }
-                    FailureKind::MentionsParam => {
-                        return Err(NotConstEvaluatable::MentionsParam);
-                    }
-                    FailureKind::Concrete => {
-                        // Dealt with below by the same code which handles this
-                        // without the feature gate.
-                    }
-                }
+        if let Some(ct) = AbstractConst::new(tcx, uv)? {
+            if satisfied_from_param_env(tcx, ct, param_env)? {
+                return Ok(());
             }
-            None => {
-                // If we are dealing with a concrete constant, we can
-                // reuse the old code path and try to evaluate
-                // the constant.
+
+            // We were unable to unify the abstract constant with
+            // a constant found in the caller bounds, there are
+            // now three possible cases here.
+            #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+            enum FailureKind {
+                /// The abstract const still references an inference
+                /// variable, in this case we return `TooGeneric`.
+                MentionsInfer,
+                /// The abstract const references a generic parameter,
+                /// this means that we emit an error here.
+                MentionsParam,
+                /// The substs are concrete enough that we can simply
+                /// try and evaluate the given constant.
+                Concrete,
+            }
+            let mut failure_kind = FailureKind::Concrete;
+            walk_abstract_const::<!, _>(tcx, ct, |node| match node.root(tcx) {
+                Node::Leaf(leaf) => {
+                    if leaf.has_infer_types_or_consts() {
+                        failure_kind = FailureKind::MentionsInfer;
+                    } else if leaf.has_param_types_or_consts() {
+                        failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
+                    }
+
+                    ControlFlow::CONTINUE
+                }
+                Node::Cast(_, _, ty) => {
+                    if ty.has_infer_types_or_consts() {
+                        failure_kind = FailureKind::MentionsInfer;
+                    } else if ty.has_param_types_or_consts() {
+                        failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
+                    }
+
+                    ControlFlow::CONTINUE
+                }
+                Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
+                    ControlFlow::CONTINUE
+                }
+            });
+
+            match failure_kind {
+                FailureKind::MentionsInfer => {
+                    return Err(NotConstEvaluatable::MentionsInfer);
+                }
+                FailureKind::MentionsParam => {
+                    return Err(NotConstEvaluatable::MentionsParam);
+                }
+                // returned below
+                FailureKind::Concrete => {}
             }
         }
-    }
-
-    let future_compat_lint = || {
-        if let Some(local_def_id) = uv.def.did.as_local() {
-            infcx.tcx.struct_span_lint_hir(
-                lint::builtin::CONST_EVALUATABLE_UNCHECKED,
-                infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
-                span,
-                |err| {
-                    err.build("cannot use constants which depend on generic parameters in types")
-                        .emit();
-                },
-            );
-        }
-    };
-
-    // FIXME: We should only try to evaluate a given constant here if it is fully concrete
-    // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
-    //
-    // We previously did not check this, so we only emit a future compat warning if
-    // const evaluation succeeds and the given constant is still polymorphic for now
-    // and hopefully soon change this to an error.
-    //
-    // See #74595 for more details about this.
-    let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
-
-    if concrete.is_ok() && uv.substs.has_param_types_or_consts() {
-        match infcx.tcx.def_kind(uv.def.did) {
-            DefKind::AnonConst | DefKind::InlineConst => {
-                let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
-
-                if mir_body.is_polymorphic {
-                    future_compat_lint();
-                }
+        let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
+        match concrete {
+            Err(ErrorHandled::TooGeneric) => Err(if !uv.has_infer_types_or_consts() {
+                infcx
+                    .tcx
+                    .sess
+                    .delay_span_bug(span, &format!("unexpected `TooGeneric` for {:?}", uv));
+                NotConstEvaluatable::MentionsParam
+            } else {
+                NotConstEvaluatable::MentionsInfer
+            }),
+            Err(ErrorHandled::Linted) => {
+                let reported = infcx
+                    .tcx
+                    .sess
+                    .delay_span_bug(span, "constant in type had error reported as lint");
+                Err(NotConstEvaluatable::Error(reported))
             }
-            _ => future_compat_lint(),
+            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+            Ok(_) => Ok(()),
         }
-    }
+    } else {
+        // FIXME: We should only try to evaluate a given constant here if it is fully concrete
+        // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
+        //
+        // We previously did not check this, so we only emit a future compat warning if
+        // const evaluation succeeds and the given constant is still polymorphic for now
+        // and hopefully soon change this to an error.
+        //
+        // See #74595 for more details about this.
+        let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
 
-    // If we're evaluating a foreign constant, under a nightly compiler without generic
-    // const exprs, AND it would've passed if that expression had been evaluated with
-    // generic const exprs, then suggest using generic const exprs.
-    if concrete.is_err()
-        && tcx.sess.is_nightly_build()
-        && !uv.def.did.is_local()
-        && !tcx.features().generic_const_exprs
-        && let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
-        && satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
-    {
-        tcx.sess
-            .struct_span_fatal(
-                // Slightly better span than just using `span` alone
-                if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
-                "failed to evaluate generic const expression",
-            )
-            .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
-            .span_suggestion_verbose(
-                rustc_span::DUMMY_SP,
-                "consider enabling this feature",
-                "#![feature(generic_const_exprs)]\n".to_string(),
-                rustc_errors::Applicability::MaybeIncorrect,
-            )
-            .emit()
-    }
+        match concrete {
+          // If we're evaluating a foreign constant, under a nightly compiler without generic
+          // const exprs, AND it would've passed if that expression had been evaluated with
+          // generic const exprs, then suggest using generic const exprs.
+          Err(_) if tcx.sess.is_nightly_build()
+            && let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
+            && satisfied_from_param_env(tcx, ct, param_env) == Ok(true) => {
+              tcx.sess
+                  .struct_span_fatal(
+                      // Slightly better span than just using `span` alone
+                      if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
+                      "failed to evaluate generic const expression",
+                  )
+                  .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
+                  .span_suggestion_verbose(
+                      rustc_span::DUMMY_SP,
+                      "consider enabling this feature",
+                      "#![feature(generic_const_exprs)]\n".to_string(),
+                      rustc_errors::Applicability::MaybeIncorrect,
+                  )
+                  .emit()
+            }
 
-    debug!(?concrete, "is_const_evaluatable");
-    match concrete {
-        Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
-            true => NotConstEvaluatable::MentionsInfer,
-            false => NotConstEvaluatable::MentionsParam,
-        }),
-        Err(ErrorHandled::Linted) => {
-            let reported =
-                infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
-            Err(NotConstEvaluatable::Error(reported))
+            Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
+                NotConstEvaluatable::MentionsInfer
+                } else {
+                NotConstEvaluatable::MentionsParam
+            }),
+            Err(ErrorHandled::Linted) => {
+                let reported =
+                    infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
+                Err(NotConstEvaluatable::Error(reported))
+            }
+            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+            Ok(_) => {
+              if uv.substs.has_param_types_or_consts() {
+                  assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
+                  let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
+
+                  if mir_body.is_polymorphic {
+                      let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
+                      tcx.struct_span_lint_hir(
+                          lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+                          tcx.hir().local_def_id_to_hir_id(local_def_id),
+                          span,
+                          |err| {
+                              err.build("cannot use constants which depend on generic parameters in types").emit();
+                        })
+                  }
+              }
+
+              Ok(())
+            },
         }
-        Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
-        Ok(_) => Ok(()),
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8181953..dcfdff6 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -62,7 +62,7 @@
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
 pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::NonStructuralMatchTy;
+pub use self::structural_match::{NonStructuralMatchTy, NonStructuralMatchTyKind};
 pub use self::util::{
     elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
     elaborate_trait_ref, elaborate_trait_refs,
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
index 7d41819..ed7d16f 100644
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
@@ -89,8 +89,8 @@
                         None,
                     )
                 })?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
+            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
+                if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
                     errored = Some(guar);
                 }
                 true
@@ -226,14 +226,12 @@
                 condition,
                 &tcx.sess.parse_sess,
                 Some(tcx.features()),
-                &mut |c| {
-                    c.ident().map_or(false, |ident| {
-                        let value = c.value_str().map(|s| {
-                            OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
-                        });
+                &mut |cfg| {
+                    let value = cfg.value.map(|v| {
+                        OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
+                    });
 
-                        options.contains(&(ident.name, value))
-                    })
+                    options.contains(&(cfg.name, value))
                 },
             ) {
                 debug!("evaluate: skipping {:?} due to condition", command);
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 07720ba..c8b4303 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -539,8 +539,16 @@
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
+                // Before we create the substitutions and everything, first
+                // consider a "quick reject". This avoids creating more types
+                // and so forth that we need to.
+                let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+                if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
+                    return;
+                }
+
                 self.infcx.probe(|_| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
+                    if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
                         candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                 });
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b0b17d0..c7ebc19 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -33,11 +33,11 @@
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
+use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
 use rustc_span::symbol::sym;
@@ -2043,7 +2043,8 @@
         impl_def_id: DefId,
         obligation: &TraitObligation<'tcx>,
     ) -> Normalized<'tcx, SubstsRef<'tcx>> {
-        match self.match_impl(impl_def_id, obligation) {
+        let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+        match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
             Ok(substs) => substs,
             Err(()) => {
                 self.infcx.tcx.sess.delay_span_bug(
@@ -2070,17 +2071,9 @@
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
+        impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
         obligation: &TraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
-
-        // Before we create the substitutions and everything, first
-        // consider a "quick reject". This avoids creating more types
-        // and so forth that we need to.
-        if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
-            return Err(());
-        }
-
         let placeholder_obligation =
             self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
         let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
@@ -2137,40 +2130,9 @@
         // We can avoid creating type variables and doing the full
         // substitution if we find that any of the input types, when
         // simplified, do not match.
-
-        iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs).any(
-            |(obligation_arg, impl_arg)| {
-                match (obligation_arg.unpack(), impl_arg.unpack()) {
-                    (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => {
-                        // Note, we simplify parameters for the obligation but not the
-                        // impl so that we do not reject a blanket impl but do reject
-                        // more concrete impls if we're searching for `T: Trait`.
-                        let simplified_obligation_ty = fast_reject::simplify_type(
-                            self.tcx(),
-                            obligation_ty,
-                            TreatParams::AsPlaceholder,
-                        );
-                        let simplified_impl_ty =
-                            fast_reject::simplify_type(self.tcx(), impl_ty, TreatParams::AsInfer);
-
-                        simplified_obligation_ty.is_some()
-                            && simplified_impl_ty.is_some()
-                            && simplified_obligation_ty != simplified_impl_ty
-                    }
-                    (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => {
-                        // Lifetimes can never cause a rejection.
-                        false
-                    }
-                    (GenericArgKind::Const(_), GenericArgKind::Const(_)) => {
-                        // Conservatively ignore consts (i.e. assume they might
-                        // unify later) until we have `fast_reject` support for
-                        // them (if we'll ever need it, even).
-                        false
-                    }
-                    _ => unreachable!(),
-                }
-            },
-        )
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        iter::zip(obligation.predicate.skip_binder().trait_ref.substs, impl_trait_ref.substs)
+            .any(|(obl, imp)| !drcx.generic_args_may_unify(obl, imp))
     }
 
     /// Normalize `where_clause_trait_ref` and try to match it against
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 67e3bf8..5465395 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -11,7 +11,13 @@
 use std::ops::ControlFlow;
 
 #[derive(Debug)]
-pub enum NonStructuralMatchTy<'tcx> {
+pub struct NonStructuralMatchTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub kind: NonStructuralMatchTyKind<'tcx>,
+}
+
+#[derive(Debug)]
+pub enum NonStructuralMatchTyKind<'tcx> {
     Adt(AdtDef<'tcx>),
     Param,
     Dynamic,
@@ -137,25 +143,32 @@
         let (adt_def, substs) = match *ty.kind() {
             ty::Adt(adt_def, substs) => (adt_def, substs),
             ty::Param(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Param);
+                let kind = NonStructuralMatchTyKind::Param;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Dynamic(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
+                let kind = NonStructuralMatchTyKind::Dynamic;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Foreign(_) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Foreign);
+                let kind = NonStructuralMatchTyKind::Foreign;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Opaque(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Opaque);
+                let kind = NonStructuralMatchTyKind::Opaque;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Projection(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Projection);
+                let kind = NonStructuralMatchTyKind::Projection;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Closure(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Closure);
+                let kind = NonStructuralMatchTyKind::Closure;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::Generator(..) | ty::GeneratorWitness(..) => {
-                return ControlFlow::Break(NonStructuralMatchTy::Generator);
+                let kind = NonStructuralMatchTyKind::Generator;
+                return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
             }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
@@ -215,7 +228,8 @@
 
         if !self.type_marked_structural(ty) {
             debug!("Search found ty: {:?}", ty);
-            return ControlFlow::Break(NonStructuralMatchTy::Adt(adt_def));
+            let kind = NonStructuralMatchTyKind::Adt(adt_def);
+            return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
         }
 
         // structural-match does not care about the
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 5096686..5c0c5b2 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -827,7 +827,9 @@
                     );
                 }
 
-                if traits::search_for_structural_match_violation(param.span, tcx, ty).is_some() {
+                if let Some(non_structural_match_ty) =
+                    traits::search_for_structural_match_violation(param.span, tcx, ty)
+                {
                     // We use the same error code in both branches, because this is really the same
                     // issue: we just special-case the message for type parameters to make it
                     // clearer.
@@ -853,19 +855,23 @@
                         )
                         .emit();
                     } else {
-                        struct_span_err!(
+                        let mut diag = struct_span_err!(
                             tcx.sess,
                             hir_ty.span,
                             E0741,
                             "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
                             the type of a const parameter",
-                            ty,
-                        )
-                        .span_label(
-                            hir_ty.span,
-                            format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
-                        )
-                        .emit();
+                            non_structural_match_ty.ty,
+                        );
+
+                        if ty == non_structural_match_ty.ty {
+                            diag.span_label(
+                                hir_ty.span,
+                                format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
+                            );
+                        }
+
+                        diag.emit();
                     }
                 }
             } else {
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 16096ea..4fe5b26 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -263,8 +263,6 @@
         self.fix_scalar_builtin_expr(e);
         self.fix_index_builtin_expr(e);
 
-        self.visit_node_id(e.span, e.hir_id);
-
         match e.kind {
             hir::ExprKind::Closure(_, _, body, _, _) => {
                 let body = self.fcx.tcx.hir().body(body);
@@ -291,6 +289,7 @@
             _ => {}
         }
 
+        self.visit_node_id(e.span, e.hir_id);
         intravisit::walk_expr(self, e);
     }
 
diff --git a/config.toml.example b/config.toml.example
index dd88687..a810e8c 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -240,10 +240,6 @@
 # Indicate whether git submodules are managed and updated automatically.
 #submodules = true
 
-# Update git submodules only when the checked out commit in the submodules differs
-# from what is committed in the main rustc repo.
-#fast-submodules = true
-
 # The path to (or name of) the GDB executable to use. This is only used for
 # executing the debuginfo test suite.
 #gdb = "gdb"
@@ -609,16 +605,9 @@
 # development of NLL
 #test-compare-mode = false
 
-# Use LLVM libunwind as the implementation for Rust's unwinder.
-# Accepted values are 'in-tree' (formerly true), 'system' or 'no' (formerly false).
-# This option only applies for Linux and Fuchsia targets.
-# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
-# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
-# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
-# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
-# means static link to the in-tree build of llvm libunwind, and 'system' means
-# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
-# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
+# Global default for llvm-libunwind for all targets. See the target-specific
+# documentation for llvm-libunwind below. Note that the target-specific
+# option will override this if set.
 #llvm-libunwind = 'no'
 
 # Enable Windows Control Flow Guard checks in the standard library.
@@ -675,6 +664,18 @@
 # not, you can specify an explicit file name for it.
 #llvm-filecheck = "/path/to/llvm-version/bin/FileCheck"
 
+# Use LLVM libunwind as the implementation for Rust's unwinder.
+# Accepted values are 'in-tree' (formerly true), 'system' or 'no' (formerly false).
+# This option only applies for Linux and Fuchsia targets.
+# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
+# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
+# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
+# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
+# means static link to the in-tree build of llvm libunwind, and 'system' means
+# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
+# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
+#llvm-libunwind = 'no' if Linux, 'in-tree' if Fuchsia
+
 # If this target is for Android, this option will be required to specify where
 # the NDK for the target lives. This is used to find the C compiler to link and
 # build native code.
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 0eaa263..39dfd98 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -383,15 +383,23 @@
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_lowercase(&self) -> String {
-        let mut s = String::with_capacity(self.len());
-        for (i, c) in self[..].char_indices() {
+        let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_lowercase);
+
+        // Safety: we know this is a valid char boundary since
+        // out.len() is only progressed if ascii bytes are found
+        let rest = unsafe { self.get_unchecked(out.len()..) };
+
+        // Safety: We have written only valid ASCII to our vec
+        let mut s = unsafe { String::from_utf8_unchecked(out) };
+
+        for (i, c) in rest[..].char_indices() {
             if c == 'Σ' {
                 // Σ maps to σ, except at the end of a word where it maps to ς.
                 // This is the only conditional (contextual) but language-independent mapping
                 // in `SpecialCasing.txt`,
                 // so hard-code it rather than have a generic "condition" mechanism.
                 // See https://github.com/rust-lang/rust/issues/26035
-                map_uppercase_sigma(self, i, &mut s)
+                map_uppercase_sigma(rest, i, &mut s)
             } else {
                 match conversions::to_lower(c) {
                     [a, '\0', _] => s.push(a),
@@ -466,8 +474,16 @@
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_uppercase(&self) -> String {
-        let mut s = String::with_capacity(self.len());
-        for c in self[..].chars() {
+        let out = convert_while_ascii(self.as_bytes(), u8::to_ascii_uppercase);
+
+        // Safety: we know this is a valid char boundary since
+        // out.len() is only progressed if ascii bytes are found
+        let rest = unsafe { self.get_unchecked(out.len()..) };
+
+        // Safety: We have written only valid ASCII to our vec
+        let mut s = unsafe { String::from_utf8_unchecked(out) };
+
+        for c in rest.chars() {
             match conversions::to_upper(c) {
                 [a, '\0', _] => s.push(a),
                 [a, b, '\0'] => {
@@ -619,3 +635,51 @@
 pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
     unsafe { Box::from_raw(Box::into_raw(v) as *mut str) }
 }
+
+/// Converts the bytes while the bytes are still ascii.
+/// For better average performance, this is happens in chunks of `2*size_of::<usize>()`.
+/// Returns a vec with the converted bytes.
+#[inline]
+#[cfg(not(test))]
+#[cfg(not(no_global_oom_handling))]
+fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> {
+    let mut out = Vec::with_capacity(b.len());
+
+    const USIZE_SIZE: usize = mem::size_of::<usize>();
+    const MAGIC_UNROLL: usize = 2;
+    const N: usize = USIZE_SIZE * MAGIC_UNROLL;
+    const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]);
+
+    let mut i = 0;
+    unsafe {
+        while i + N <= b.len() {
+            // Safety: we have checks the sizes `b` and `out` to know that our
+            let in_chunk = b.get_unchecked(i..i + N);
+            let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N);
+
+            let mut bits = 0;
+            for j in 0..MAGIC_UNROLL {
+                // read the bytes 1 usize at a time (unaligned since we haven't checked the alignment)
+                // safety: in_chunk is valid bytes in the range
+                bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned();
+            }
+            // if our chunks aren't ascii, then return only the prior bytes as init
+            if bits & NONASCII_MASK != 0 {
+                break;
+            }
+
+            // perform the case conversions on N bytes (gets heavily autovec'd)
+            for j in 0..N {
+                // safety: in_chunk and out_chunk is valid bytes in the range
+                let out = out_chunk.get_unchecked_mut(j);
+                out.write(convert(in_chunk.get_unchecked(j)));
+            }
+
+            // mark these bytes as initialised
+            i += N;
+        }
+        out.set_len(i);
+    }
+
+    out
+}
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 273b39a..7379569 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1772,6 +1772,20 @@
     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
+
+    // a really long string that has it's lowercase form
+    // even longer. this tests that implementations don't assume
+    // an incorrect upper bound on allocations
+    let upper = str::repeat("İ", 512);
+    let lower = str::repeat("i̇", 512);
+    assert_eq!(upper.to_lowercase(), lower);
+
+    // a really long ascii-only string.
+    // This test that the ascii hot-path
+    // functions correctly
+    let upper = str::repeat("A", 511);
+    let lower = str::repeat("a", 511);
+    assert_eq!(upper.to_lowercase(), lower);
 }
 
 #[test]
diff --git a/library/core/src/asserting.rs b/library/core/src/asserting.rs
new file mode 100644
index 0000000..212b637
--- /dev/null
+++ b/library/core/src/asserting.rs
@@ -0,0 +1,109 @@
+// Contains the machinery necessary to print useful `assert!` messages. Not intended for public
+// usage, not even nightly use-cases.
+//
+// Based on https://github.com/dtolnay/case-studies/tree/master/autoref-specialization. When
+// 'specialization' is robust enough (5 years? 10 years? Never?), `Capture` can be specialized
+// to [Printable].
+
+#![allow(missing_debug_implementations)]
+#![doc(hidden)]
+#![unstable(feature = "generic_assert_internals", issue = "44838")]
+
+use crate::{
+    fmt::{Debug, Formatter},
+    marker::PhantomData,
+};
+
+// ***** TryCapture - Generic *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithoutDebug;
+
+/// Catches an arbitrary `E` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCaptureGeneric<E, M> {
+    /// Similar to [TryCapturePrintable] but generic to any `E`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCaptureGeneric<E, TryCaptureWithoutDebug> for &Wrapper<&E> {
+    #[inline]
+    fn try_capture(&self, _: &mut Capture<E, TryCaptureWithoutDebug>) {}
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithoutDebug> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        f.write_str("N/A")
+    }
+}
+
+// ***** TryCapture - Printable *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithDebug;
+
+/// Catches an arbitrary `E: Printable` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCapturePrintable<E, M> {
+    /// Similar as [TryCaptureGeneric] but specialized to any `E: Printable`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCapturePrintable<E, TryCaptureWithDebug> for Wrapper<&E>
+where
+    E: Printable,
+{
+    #[inline]
+    fn try_capture(&self, to: &mut Capture<E, TryCaptureWithDebug>) {
+        to.elem = Some(*self.0);
+    }
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithDebug>
+where
+    E: Printable,
+{
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        match self.elem {
+            None => f.write_str("N/A"),
+            Some(ref value) => Debug::fmt(value, f),
+        }
+    }
+}
+
+// ***** Others *****
+
+/// All possible captured `assert!` elements
+///
+/// # Types
+///
+/// * `E`: **E**lement that is going to be displayed.
+/// * `M`: **M**arker used to differentiate [Capture]s in regards to [Debug].
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Capture<E, M> {
+    // If None, then `E` does not implements [Printable] or `E` wasn't evaluated (`assert!( ... )`
+    // short-circuited).
+    //
+    // If Some, then `E` implements [Printable] and was evaluated.
+    pub elem: Option<E>,
+    phantom: PhantomData<M>,
+}
+
+impl<M, T> Capture<M, T> {
+    #[inline]
+    pub const fn new() -> Self {
+        Self { elem: None, phantom: PhantomData }
+    }
+}
+
+/// Necessary for the implementations of `TryCapture*`
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Wrapper<T>(pub T);
+
+/// Tells which elements can be copied and displayed
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait Printable: Copy + Debug {}
+
+impl<T> Printable for T where T: Copy + Debug {}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 9884b7f..321f2fe 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1390,8 +1390,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(cell_filter_map)]
-    ///
     /// use std::cell::{RefCell, Ref};
     ///
     /// let c = RefCell::new(vec![1, 2, 3]);
@@ -1399,7 +1397,7 @@
     /// let b2: Result<Ref<u32>, _> = Ref::filter_map(b1, |v| v.get(1));
     /// assert_eq!(*b2.unwrap(), 2);
     /// ```
-    #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+    #[stable(feature = "cell_filter_map", since = "1.63.0")]
     #[inline]
     pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Result<Ref<'b, U>, Self>
     where
@@ -1538,8 +1536,6 @@
     /// # Examples
     ///
     /// ```
-    /// #![feature(cell_filter_map)]
-    ///
     /// use std::cell::{RefCell, RefMut};
     ///
     /// let c = RefCell::new(vec![1, 2, 3]);
@@ -1555,7 +1551,7 @@
     ///
     /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
     /// ```
-    #[unstable(feature = "cell_filter_map", reason = "recently added", issue = "81061")]
+    #[stable(feature = "cell_filter_map", since = "1.63.0")]
     #[inline]
     pub fn filter_map<U: ?Sized, F>(mut orig: RefMut<'b, T>, f: F) -> Result<RefMut<'b, U>, Self>
     where
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 88e4262..6ba359f 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -930,6 +930,9 @@
     /// fn foo() -> i32 {
     ///     0
     /// }
+    /// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
+    /// // This avoids an integer-to-pointer `transmute`, which can be problematic.
+    /// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
     /// let pointer = foo as *const ();
     /// let function = unsafe {
     ///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7b04e44..cfcc3ff 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -310,6 +310,7 @@
 pub mod any;
 pub mod array;
 pub mod ascii;
+pub mod asserting;
 #[unstable(feature = "async_iterator", issue = "79024")]
 pub mod async_iter;
 pub mod cell;
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index d074669..28ea45e 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -708,6 +708,26 @@
     /// let x: Option<&str> = None;
     /// x.expect("fruits are healthy"); // panics with `fruits are healthy`
     /// ```
+    ///
+    /// # Recommended Message Style
+    ///
+    /// We recommend that `expect` messages are used to describe the reason you
+    /// _expect_ the `Option` should be `Some`.
+    ///
+    /// ```should_panic
+    /// # let slice: &[u8] = &[];
+    /// let item = slice.get(0)
+    ///     .expect("slice should not be empty");
+    /// ```
+    ///
+    /// **Hint**: If you're having trouble remembering how to phrase expect
+    /// error messages remember to focus on the word "should" as in "env
+    /// variable should be set by blah" or "the given binary should be available
+    /// and executable by the current user".
+    ///
+    /// For more detail on expect message styles and the reasoning behind our
+    /// recommendation please refer to the section on ["Common Message
+    /// Styles"](../../std/error/index.html#common-message-styles) in the [`std::error`](../../std/error/index.html) module docs.
     #[inline]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 631cc31..688ab63 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1351,6 +1351,32 @@
 /// is a reference to the function-specific ZST. `&bar` is basically never what you
 /// want when `bar` is a function.
 ///
+/// ### Casting to and from integers
+///
+/// You cast function pointers directly to integers:
+///
+/// ```rust
+/// let fnptr: fn(i32) -> i32 = |x| x+2;
+/// let fnptr_addr = fnptr as usize;
+/// ```
+///
+/// However, a direct cast back is not possible. You need to use `transmute`:
+///
+/// ```rust
+/// # let fnptr: fn(i32) -> i32 = |x| x+2;
+/// # let fnptr_addr = fnptr as usize;
+/// let fnptr = fnptr_addr as *const ();
+/// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
+/// assert_eq!(fnptr(40), 42);
+/// ```
+///
+/// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
+/// This avoids an integer-to-pointer `transmute`, which can be problematic.
+/// Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
+///
+/// Note that all of this is not portable to platforms where function pointers and data pointers
+/// have different sizes.
+///
 /// ### Traits
 ///
 /// Function pointers implement the following traits:
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index dc229c9..d2e680e 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -507,10 +507,33 @@
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
 #[rustc_diagnostic_item = "ptr_null"]
+#[cfg(bootstrap)]
 pub const fn null<T>() -> *const T {
     invalid(0)
 }
 
+/// Creates a null raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *const i32 = ptr::null();
+/// assert!(p.is_null());
+/// ```
+#[inline(always)]
+#[must_use]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_null"]
+#[cfg(not(bootstrap))]
+pub const fn null<T: ?Sized + Thin>() -> *const T {
+    from_raw_parts(0 as *const (), ())
+}
+
 /// Creates a null mutable raw pointer.
 ///
 /// # Examples
@@ -527,6 +550,7 @@
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
 #[rustc_diagnostic_item = "ptr_null_mut"]
+#[cfg(bootstrap)]
 pub const fn null_mut<T>() -> *mut T {
     invalid_mut(0)
 }
@@ -665,6 +689,28 @@
     addr as *mut T
 }
 
+/// Creates a null mutable raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *mut i32 = ptr::null_mut();
+/// assert!(p.is_null());
+/// ```
+#[inline(always)]
+#[must_use]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_null_mut"]
+#[cfg(not(bootstrap))]
+pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
+    from_raw_parts_mut(0 as *mut (), ())
+}
+
 /// Forms a raw slice from a pointer and a length.
 ///
 /// The `len` argument is the number of **elements**, not the number of bytes.
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 5e5f8a5..c4dc34f 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1023,6 +1023,26 @@
     /// let x: Result<u32, &str> = Err("emergency failure");
     /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
     /// ```
+    ///
+    /// # Recommended Message Style
+    ///
+    /// We recommend that `expect` messages are used to describe the reason you
+    /// _expect_ the `Result` should be `Ok`.
+    ///
+    /// ```should_panic
+    /// let path = std::env::var("IMPORTANT_PATH")
+    ///     .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`");
+    /// ```
+    ///
+    /// **Hint**: If you're having trouble remembering how to phrase expect
+    /// error messages remember to focus on the word "should" as in "env
+    /// variable should be set by blah" or "the given binary should be available
+    /// and executable by the current user".
+    ///
+    /// For more detail on expect message styles and the reasoning behind our recommendation please
+    /// refer to the section on ["Common Message
+    /// Styles"](../../std/error/index.html#common-message-styles) in the
+    /// [`std::error`](../../std/error/index.html) module docs.
     #[inline]
     #[track_caller]
     #[stable(feature = "result_expect", since = "1.4.0")]
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 68de4e4..fd7ecf3 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -138,7 +138,7 @@
 /// A helper trait used for indexing operations.
 ///
 /// Implementations of this trait have to promise that if the argument
-/// to `get_(mut_)unchecked` is a safe reference, then so is the result.
+/// to `get_unchecked(_mut)` is a safe reference, then so is the result.
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 #[rustc_diagnostic_item = "SliceIndex"]
 #[rustc_on_unimplemented(
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 36df5c3..43cfb1b 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1517,7 +1517,7 @@
         #[$stable_debug]
         impl fmt::Debug for $atomic_type {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
+                fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
             }
         }
 
@@ -2996,7 +2996,7 @@
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl fmt::Debug for AtomicBool {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
+        fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
     }
 }
 
@@ -3004,7 +3004,7 @@
 #[stable(feature = "atomic_debug", since = "1.3.0")]
 impl<T> fmt::Debug for AtomicPtr<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
+        fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
     }
 }
 
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 413fe7e..87d4a25 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -218,6 +218,19 @@
 
 impl Waker {
     /// Wake up the task associated with this `Waker`.
+    ///
+    /// As long as the runtime keeps running and the task is not finished, it is
+    /// guaranteed that each invocation of `wake` (or `wake_by_ref`) will be followed
+    /// by at least one `poll` of the task to which this `Waker` belongs. This makes
+    /// it possible to temporarily yield to other tasks while running potentially
+    /// unbounded processing loops.
+    ///
+    /// Note that the above implies that multiple wake-ups may be coalesced into a
+    /// single `poll` invocation by the runtime.
+    ///
+    /// Also note that yielding to competing tasks is not guaranteed: it is the
+    /// executor’s choice which task to run and the executor may choose to run the
+    /// current task again.
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub fn wake(self) {
diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs
new file mode 100644
index 0000000..4b626ba
--- /dev/null
+++ b/library/core/tests/asserting.rs
@@ -0,0 +1,37 @@
+use core::asserting::{Capture, TryCaptureGeneric, TryCapturePrintable, Wrapper};
+
+macro_rules! test {
+    ($test_name:ident, $elem:expr, $captured_elem:expr, $output:literal) => {
+        #[test]
+        fn $test_name() {
+            let elem = $elem;
+            let mut capture = Capture::new();
+            assert!(capture.elem == None);
+            (&Wrapper(&elem)).try_capture(&mut capture);
+            assert!(capture.elem == $captured_elem);
+            assert_eq!(format!("{:?}", capture), $output);
+        }
+    };
+}
+
+#[derive(Debug, PartialEq)]
+struct NoCopy;
+
+#[derive(PartialEq)]
+struct NoCopyNoDebug;
+
+#[derive(Clone, Copy, PartialEq)]
+struct NoDebug;
+
+test!(
+    capture_with_non_copyable_and_non_debugabble_elem_has_correct_params,
+    NoCopyNoDebug,
+    None,
+    "N/A"
+);
+
+test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A");
+
+test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A");
+
+test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1");
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 004589b..9ea374e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -35,6 +35,7 @@
 #![feature(float_minimum_maximum)]
 #![feature(future_join)]
 #![feature(future_poll_fn)]
+#![feature(generic_assert_internals)]
 #![feature(array_try_from_fn)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
@@ -104,6 +105,7 @@
 mod any;
 mod array;
 mod ascii;
+mod asserting;
 mod atomic;
 mod bool;
 mod cell;
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 03fe560..c5242ad 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -93,6 +93,18 @@
 
     let nmi: *mut dyn ToString = null_mut::<isize>();
     assert!(nmi.is_null());
+
+    #[cfg(not(bootstrap))]
+    {
+        extern "C" {
+            type Extern;
+        }
+        let ec: *const Extern = null::<Extern>();
+        assert!(ec.is_null());
+
+        let em: *mut Extern = null_mut::<Extern>();
+        assert!(em.is_null());
+    }
 }
 
 #[test]
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 4027a71..463f714 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -49,6 +49,9 @@
 ///     Ok(())
 /// }
 /// ```
+#[doc(alias = "pwd")]
+#[doc(alias = "getcwd")]
+#[doc(alias = "GetCurrentDirectory")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn current_dir() -> io::Result<PathBuf> {
     os_imp::getcwd()
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 438304e..c2d3061 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -1,4 +1,140 @@
-//! Traits for working with Errors.
+//! Interfaces for working with Errors.
+//!
+//! # Error Handling In Rust
+//!
+//! The Rust language provides two complementary systems for constructing /
+//! representing, reporting, propagating, reacting to, and discarding errors.
+//! These responsibilities are collectively known as "error handling." The
+//! components of the first system, the panic runtime and interfaces, are most
+//! commonly used to represent bugs that have been detected in your program. The
+//! components of the second system, `Result`, the error traits, and user
+//! defined types, are used to represent anticipated runtime failure modes of
+//! your program.
+//!
+//! ## The Panic Interfaces
+//!
+//! The following are the primary interfaces of the panic system and the
+//! responsibilities they cover:
+//!
+//! * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
+//! * [`PanicInfo`] (Reporting)
+//! * [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting)
+//! * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)
+//!
+//! The following are the primary interfaces of the error system and the
+//! responsibilities they cover:
+//!
+//! * [`Result`] (Propagating, Reacting)
+//! * The [`Error`] trait (Reporting)
+//! * User defined types (Constructing / Representing)
+//! * [`match`] and [`downcast`] (Reacting)
+//! * The question mark operator ([`?`]) (Propagating)
+//! * The partially stable [`Try`] traits (Propagating, Constructing)
+//! * [`Termination`] (Reporting)
+//!
+//! ## Converting Errors into Panics
+//!
+//! The panic and error systems are not entirely distinct. Often times errors
+//! that are anticipated runtime failures in an API might instead represent bugs
+//! to a caller. For these situations the standard library provides APIs for
+//! constructing panics with an `Error` as it's source.
+//!
+//! * [`Result::unwrap`]
+//! * [`Result::expect`]
+//!
+//! These functions are equivalent, they either return the inner value if the
+//! `Result` is `Ok` or panic if the `Result` is `Err` printing the inner error
+//! as the source. The only difference between them is that with `expect` you
+//! provide a panic error message to be printed alongside the source, whereas
+//! `unwrap` has a default message indicating only that you unwraped an `Err`.
+//!
+//! Of the two, `expect` is generally preferred since its `msg` field allows you
+//! to convey your intent and assumptions which makes tracking down the source
+//! of a panic easier. `unwrap` on the other hand can still be a good fit in
+//! situations where you can trivially show that a piece of code will never
+//! panick, such as `"127.0.0.1".parse::<std::net::IpAddr>().unwrap()` or early
+//! prototyping.
+//!
+//! # Common Message Styles
+//!
+//! There are two common styles for how people word `expect` messages. Using
+//! the message to present information to users encountering a panic
+//! ("expect as error message") or using the message to present information
+//! to developers debugging the panic ("expect as precondition").
+//!
+//! In the former case the expect message is used to describe the error that
+//! has occurred which is considered a bug. Consider the following example:
+//!
+//! ```should_panic
+//! // Read environment variable, panic if it is not present
+//! let path = std::env::var("IMPORTANT_PATH").unwrap();
+//! ```
+//!
+//! In the "expect as error message" style we would use expect to describe
+//! that the environment variable was not set when it should have been:
+//!
+//! ```should_panic
+//! let path = std::env::var("IMPORTANT_PATH")
+//!     .expect("env variable `IMPORTANT_PATH` is not set");
+//! ```
+//!
+//! In the "expect as precondition" style, we would instead describe the
+//! reason we _expect_ the `Result` should be `Ok`. With this style we would
+//! prefer to write:
+//!
+//! ```should_panic
+//! let path = std::env::var("IMPORTANT_PATH")
+//!     .expect("env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`");
+//! ```
+//!
+//! The "expect as error message" style does not work as well with the
+//! default output of the std panic hooks, and often ends up repeating
+//! information that is already communicated by the source error being
+//! unwrapped:
+//!
+//! ```text
+//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` is not set: NotPresent', src/main.rs:4:6
+//! ```
+//!
+//! In this example we end up mentioning that an env variable is not set,
+//! followed by our source message that says the env is not present, the
+//! only additional information we're communicating is the name of the
+//! environment variable being checked.
+//!
+//! The "expect as precondition" style instead focuses on source code
+//! readability, making it easier to understand what must have gone wrong in
+//! situations where panics are being used to represent bugs exclusively.
+//! Also, by framing our expect in terms of what "SHOULD" have happened to
+//! prevent the source error, we end up introducing new information that is
+//! independent from our source error.
+//!
+//! ```text
+//! thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`: NotPresent', src/main.rs:4:6
+//! ```
+//!
+//! In this example we are communicating not only the name of the
+//! environment variable that should have been set, but also an explanation
+//! for why it should have been set, and we let the source error display as
+//! a clear contradiction to our expectation.
+//!
+//! **Hint**: If you're having trouble remembering how to phrase
+//! expect-as-precondition style error messages remember to focus on the word
+//! "should" as in "env variable should be set by blah" or "the given binary
+//! should be available and executable by the current user".
+//!
+//! [`panic_any`]: crate::panic::panic_any
+//! [`PanicInfo`]: crate::panic::PanicInfo
+//! [`catch_unwind`]: crate::panic::catch_unwind
+//! [`resume_unwind`]: crate::panic::resume_unwind
+//! [`downcast`]: crate::error::Error
+//! [`Termination`]: crate::process::Termination
+//! [`Try`]: crate::ops::Try
+//! [panic hook]: crate::panic::set_hook
+//! [`set_hook`]: crate::panic::set_hook
+//! [`take_hook`]: crate::panic::take_hook
+//! [panic-handler]: <https://doc.rust-lang.org/nomicon/panic-handler.html>
+//! [`match`]: ../../std/keyword.match.html
+//! [`?`]: ../../std/result/index.html#the-question-mark-operator-
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index bc2384c..6dcd55c 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -70,7 +70,7 @@
 /// A break expression is normally associated with the innermost loop enclosing the
 /// `break` but a label can be used to specify which enclosing loop is affected.
 ///
-///```rust
+/// ```rust
 /// 'outer: for i in 1..=5 {
 ///     println!("outer iteration (i): {i}");
 ///
@@ -87,7 +87,7 @@
 ///     }
 /// }
 /// println!("Bye.");
-///```
+/// ```
 ///
 /// When associated with `loop`, a break expression may be used to return a value from that loop.
 /// This is only valid with `loop` and not with any other type of loop.
@@ -194,7 +194,7 @@
 /// When `continue` is encountered, the current iteration is terminated, returning control to the
 /// loop head, typically continuing with the next iteration.
 ///
-///```rust
+/// ```rust
 /// // Printing odd numbers by skipping even ones
 /// for number in 1..=10 {
 ///     if number % 2 == 0 {
@@ -202,12 +202,12 @@
 ///     }
 ///     println!("{number}");
 /// }
-///```
+/// ```
 ///
 /// Like `break`, `continue` is normally associated with the innermost enclosing loop, but labels
 /// may be used to specify the affected loop.
 ///
-///```rust
+/// ```rust
 /// // Print Odd numbers under 30 with unit <= 5
 /// 'tens: for ten in 0..3 {
 ///     '_units: for unit in 0..=9 {
@@ -220,7 +220,7 @@
 ///         println!("{}", ten * 10 + unit);
 ///     }
 /// }
-///```
+/// ```
 ///
 /// See [continue expressions] from the reference for more details.
 ///
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 46004c9..438bae0 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -1655,7 +1655,7 @@
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.62.0")]
+    #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs
index 9e31b8b..ecee123 100644
--- a/library/std/src/os/unix/net/ancillary.rs
+++ b/library/std/src/os/unix/net/ancillary.rs
@@ -1,3 +1,5 @@
+// FIXME: This is currently disabled on *BSD.
+
 use super::{sockaddr_un, SocketAddr};
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::marker::PhantomData;
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 872058b..0b1d9b0 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -1,24 +1,7 @@
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
 use super::{sockaddr_un, SocketAddr};
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use crate::io::{IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
@@ -403,7 +386,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -433,15 +417,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary_from(
         &self,
@@ -460,7 +436,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -490,15 +467,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary(
         &self,
@@ -609,7 +578,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
     /// use std::io::IoSlice;
@@ -633,15 +603,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>(
         &self,
@@ -658,7 +620,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
     /// use std::io::IoSlice;
@@ -682,15 +645,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary(
         &self,
diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs
index 8ce8220..6da3e350 100644
--- a/library/std/src/os/unix/net/mod.rs
+++ b/library/std/src/os/unix/net/mod.rs
@@ -1,27 +1,11 @@
 //! Unix-specific networking functionality.
 
+#![allow(irrefutable_let_patterns)]
 #![stable(feature = "unix_socket", since = "1.10.0")]
 
 mod addr;
-#[doc(cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-)))]
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[doc(cfg(any(target_os = "android", target_os = "linux")))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 mod ancillary;
 mod datagram;
 mod listener;
@@ -31,16 +15,7 @@
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub use self::addr::*;
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 pub use self::ancillary::*;
 #[stable(feature = "unix_socket", since = "1.10.0")]
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index cd1aa01..2a5790e 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -1,13 +1,4 @@
-#[cfg(any(
-    doc,
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
 use super::{sockaddr_un, SocketAddr};
 use crate::fmt;
@@ -511,7 +502,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
     /// use std::io::IoSliceMut;
@@ -541,15 +533,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn recv_vectored_with_ancillary(
         &self,
@@ -567,7 +551,8 @@
     ///
     /// # Examples
     ///
-    /// ```no_run
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
     /// #![feature(unix_socket_ancillary_data)]
     /// use std::os::unix::net::{UnixStream, SocketAncillary};
     /// use std::io::IoSlice;
@@ -591,15 +576,7 @@
     ///     Ok(())
     /// }
     /// ```
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(doc, target_os = "android", target_os = "linux"))]
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn send_vectored_with_ancillary(
         &self,
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index c1f11c5..e4499f9 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -1,24 +1,7 @@
 use super::*;
 use crate::io::prelude::*;
 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 use crate::os::unix::io::AsRawFd;
 use crate::sys_common::io::test::tmpdir;
 use crate::thread;
@@ -618,15 +601,7 @@
     assert_eq!(msg, &buf[..]);
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_send_vectored_fds_unix_stream() {
     let (s1, s2) = or_panic!(UnixStream::pair());
@@ -664,7 +639,7 @@
     }
 }
 
-#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux",))]
+#[cfg(any(target_os = "android", target_os = "linux",))]
 #[test]
 fn test_send_vectored_with_ancillary_to_unix_datagram() {
     fn getpid() -> libc::pid_t {
@@ -731,15 +706,7 @@
     }
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "emscripten",
-    target_os = "freebsd",
-    target_os = "linux",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 fn test_send_vectored_with_ancillary_unix_datagram() {
     let dir = tmpdir();
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 631cc31..688ab63 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1351,6 +1351,32 @@
 /// is a reference to the function-specific ZST. `&bar` is basically never what you
 /// want when `bar` is a function.
 ///
+/// ### Casting to and from integers
+///
+/// You cast function pointers directly to integers:
+///
+/// ```rust
+/// let fnptr: fn(i32) -> i32 = |x| x+2;
+/// let fnptr_addr = fnptr as usize;
+/// ```
+///
+/// However, a direct cast back is not possible. You need to use `transmute`:
+///
+/// ```rust
+/// # let fnptr: fn(i32) -> i32 = |x| x+2;
+/// # let fnptr_addr = fnptr as usize;
+/// let fnptr = fnptr_addr as *const ();
+/// let fnptr: fn(i32) -> i32 = unsafe { std::mem::transmute(fnptr) };
+/// assert_eq!(fnptr(40), 42);
+/// ```
+///
+/// Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
+/// This avoids an integer-to-pointer `transmute`, which can be problematic.
+/// Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
+///
+/// Note that all of this is not portable to platforms where function pointers and data pointers
+/// have different sizes.
+///
 /// ### Traits
 ///
 /// Function pointers implement the following traits:
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 9bf9607..a1bbc2d 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -289,15 +289,7 @@
         self.recv_from_with_flags(buf, 0)
     }
 
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(target_os = "android", target_os = "linux"))]
     pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
         let n = cvt(unsafe { libc::recvmsg(self.as_raw_fd(), msg, libc::MSG_CMSG_CLOEXEC) })?;
         Ok(n as usize)
@@ -320,15 +312,7 @@
         self.0.is_write_vectored()
     }
 
-    #[cfg(any(
-        target_os = "android",
-        target_os = "dragonfly",
-        target_os = "emscripten",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-    ))]
+    #[cfg(any(target_os = "android", target_os = "linux"))]
     pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
         let n = cvt(unsafe { libc::sendmsg(self.as_raw_fd(), msg, 0) })?;
         Ok(n as usize)
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 5324c6b..add73eb 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -11,6 +11,7 @@
 - The options `infodir`, `localstatedir`, and `gpg-password-file` are no longer allowed in config.toml. Previously, they were ignored without warning. Note that `infodir` and `localstatedir` are still accepted by `./configure`, with a warning. [#82451](https://github.com/rust-lang/rust/pull/82451)
 - Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false.
 - Change the names for `dist` commands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684)
+- The `build.fast-submodules` option has been removed. Fast submodule checkouts are enabled unconditionally. Automatic submodule handling can still be disabled with `build.submodules = false`.
 
 ### Non-breaking changes
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 6d46ea2..916c8e5 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -926,23 +926,19 @@
             return config
         return default_build_triple(self.verbose)
 
-    def check_submodule(self, module, slow_submodules):
-        if not slow_submodules:
-            checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"],
-                                           cwd=os.path.join(self.rust_root, module),
-                                           stdout=subprocess.PIPE)
-            return checked_out
-        else:
-            return None
+    def check_submodule(self, module):
+        checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"],
+                                        cwd=os.path.join(self.rust_root, module),
+                                        stdout=subprocess.PIPE)
+        return checked_out
 
     def update_submodule(self, module, checked_out, recorded_submodules):
         module_path = os.path.join(self.rust_root, module)
 
-        if checked_out is not None:
-            default_encoding = sys.getdefaultencoding()
-            checked_out = checked_out.communicate()[0].decode(default_encoding).strip()
-            if recorded_submodules[module] == checked_out:
-                return
+        default_encoding = sys.getdefaultencoding()
+        checked_out = checked_out.communicate()[0].decode(default_encoding).strip()
+        if recorded_submodules[module] == checked_out:
+            return
 
         print("Updating submodule", module)
 
@@ -991,12 +987,8 @@
         git_version_str = require(['git', '--version']).split()[2].decode(default_encoding)
         self.git_version = distutils.version.LooseVersion(git_version_str)
 
-        slow_submodules = self.get_toml('fast-submodules') == "false"
         start_time = time()
-        if slow_submodules:
-            print('Unconditionally updating submodules')
-        else:
-            print('Updating only changed submodules')
+        print('Updating only changed submodules')
         default_encoding = sys.getdefaultencoding()
         # Only update submodules that are needed to build bootstrap.  These are needed because Cargo
         # currently requires everything in a workspace to be "locally present" when starting a
@@ -1022,7 +1014,7 @@
         filtered_submodules = []
         submodules_names = []
         for module in submodules:
-            check = self.check_submodule(module, slow_submodules)
+            check = self.check_submodule(module)
             filtered_submodules.append((module, check))
             submodules_names.append(module)
         recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names,
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 761bd66..0fb66e5 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1232,7 +1232,12 @@
                 // HACK: because anyhow does feature detection in build.rs, we need to allow the backtrace feature too.
                 rustflags.arg("-Zallow-features=binary-dep-depinfo,backtrace");
             }
-            Mode::Std | Mode::Rustc | Mode::ToolStd | Mode::Codegen | Mode::ToolRustc => {}
+            Mode::ToolStd => {
+                // Right now this is just compiletest and a few other tools that build on stable.
+                // Allow them to use `feature(test)`, but nothing else.
+                rustflags.arg("-Zallow-features=binary-dep-depinfo,test,backtrace");
+            }
+            Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {}
         }
 
         cargo.arg("-j").arg(self.jobs().to_string());
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 7a8c7fe..b35eba2 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -176,7 +176,7 @@
 
     if target == "x86_64-fortanix-unknown-sgx"
         || target.contains("pc-windows-gnullvm")
-        || builder.config.llvm_libunwind == LlvmLibunwind::InTree
+        || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
             && (target.contains("linux") || target.contains("fuchsia"))
     {
         let libunwind_path =
@@ -1164,14 +1164,11 @@
             // for `-Z gcc-ld=lld`
             let gcc_ld_dir = libdir_bin.join("gcc-ld");
             t!(fs::create_dir(&gcc_ld_dir));
-            for flavor in ["ld", "ld64"] {
-                let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
-                    compiler: build_compiler,
-                    target: target_compiler.host,
-                    flavor_feature: flavor,
-                });
-                builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(flavor, target_compiler.host)));
-            }
+            let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
+                compiler: build_compiler,
+                target: target_compiler.host,
+            });
+            builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host)));
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e39c9fa..843d276 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -50,7 +50,6 @@
     pub ninja_in_file: bool,
     pub verbose: usize,
     pub submodules: Option<bool>,
-    pub fast_submodules: bool,
     pub compiler_docs: bool,
     pub docs_minification: bool,
     pub docs: bool,
@@ -68,7 +67,6 @@
     pub rustc_error_format: Option<String>,
     pub json_output: bool,
     pub test_compare_mode: bool,
-    pub llvm_libunwind: LlvmLibunwind,
     pub color: Color,
     pub patch_binaries_for_nix: bool,
 
@@ -152,6 +150,7 @@
     pub rust_profile_generate: Option<String>,
     pub llvm_profile_use: Option<String>,
     pub llvm_profile_generate: bool,
+    pub llvm_libunwind_default: Option<LlvmLibunwind>,
 
     pub build: TargetSelection,
     pub hosts: Vec<TargetSelection>,
@@ -343,6 +342,7 @@
     pub llvm_config: Option<PathBuf>,
     /// Some(path to FileCheck) if one was specified.
     pub llvm_filecheck: Option<PathBuf>,
+    pub llvm_libunwind: Option<LlvmLibunwind>,
     pub cc: Option<PathBuf>,
     pub cxx: Option<PathBuf>,
     pub ar: Option<PathBuf>,
@@ -517,7 +517,6 @@
         compiler_docs: Option<bool> = "compiler-docs",
         docs_minification: Option<bool> = "docs-minification",
         submodules: Option<bool> = "submodules",
-        fast_submodules: Option<bool> = "fast-submodules",
         gdb: Option<String> = "gdb",
         nodejs: Option<String> = "nodejs",
         npm: Option<String> = "npm",
@@ -682,6 +681,7 @@
         linker: Option<String> = "linker",
         llvm_config: Option<String> = "llvm-config",
         llvm_filecheck: Option<String> = "llvm-filecheck",
+        llvm_libunwind: Option<String> = "llvm-libunwind",
         android_ndk: Option<String> = "android-ndk",
         sanitizers: Option<bool> = "sanitizers",
         profiler: Option<bool> = "profiler",
@@ -705,7 +705,6 @@
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
         config.submodules = None;
-        config.fast_submodules = true;
         config.docs = true;
         config.docs_minification = true;
         config.rust_rpath = true;
@@ -847,7 +846,6 @@
         set(&mut config.compiler_docs, build.compiler_docs);
         set(&mut config.docs_minification, build.docs_minification);
         set(&mut config.docs, build.docs);
-        set(&mut config.fast_submodules, build.fast_submodules);
         set(&mut config.locked_deps, build.locked_deps);
         set(&mut config.vendor, build.vendor);
         set(&mut config.full_bootstrap, build.full_bootstrap);
@@ -1047,10 +1045,6 @@
             set(&mut config.rust_rpath, rust.rpath);
             set(&mut config.jemalloc, rust.jemalloc);
             set(&mut config.test_compare_mode, rust.test_compare_mode);
-            config.llvm_libunwind = rust
-                .llvm_libunwind
-                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"))
-                .unwrap_or_default();
             set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel);
             config.description = rust.description;
@@ -1073,6 +1067,9 @@
             config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
             set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
             set(&mut config.control_flow_guard, rust.control_flow_guard);
+            config.llvm_libunwind_default = rust
+                .llvm_libunwind
+                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
 
             if let Some(ref backends) = rust.codegen_backends {
                 config.rust_codegen_backends =
@@ -1099,6 +1096,10 @@
                 if let Some(ref s) = cfg.llvm_filecheck {
                     target.llvm_filecheck = Some(config.src.join(s));
                 }
+                target.llvm_libunwind = cfg
+                    .llvm_libunwind
+                    .as_ref()
+                    .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
                 if let Some(ref s) = cfg.android_ndk {
                     target.ndk = Some(config.src.join(s));
                 }
@@ -1332,6 +1333,14 @@
         self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
     }
 
+    pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
+        self.target_config
+            .get(&target)
+            .and_then(|t| t.llvm_libunwind)
+            .or(self.llvm_libunwind_default)
+            .unwrap_or(LlvmLibunwind::No)
+    }
+
     pub fn submodules(&self, rust_info: &GitInfo) -> bool {
         self.submodules.unwrap_or(rust_info.is_git())
     }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 0be11e3..cc10d67 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -407,11 +407,8 @@
                 let gcc_lld_src_dir = src_dir.join("gcc-ld");
                 let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&gcc_lld_dst_dir));
-                for flavor in ["ld", "ld64"] {
-                    let exe_name = exe(flavor, compiler.host);
-                    builder
-                        .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
-                }
+                let exe_name = exe("ld", compiler.host);
+                builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
             }
 
             // Man pages
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index a4e35bf..591f9a1 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -556,27 +556,24 @@
         }
 
         // check_submodule
-        if self.config.fast_submodules {
-            let checked_out_hash = output(
-                Command::new("git").args(&["rev-parse", "HEAD"]).current_dir(&absolute_path),
-            );
-            // update_submodules
-            let recorded = output(
-                Command::new("git")
-                    .args(&["ls-tree", "HEAD"])
-                    .arg(relative_path)
-                    .current_dir(&self.config.src),
-            );
-            let actual_hash = recorded
-                .split_whitespace()
-                .nth(2)
-                .unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
+        let checked_out_hash =
+            output(Command::new("git").args(&["rev-parse", "HEAD"]).current_dir(&absolute_path));
+        // update_submodules
+        let recorded = output(
+            Command::new("git")
+                .args(&["ls-tree", "HEAD"])
+                .arg(relative_path)
+                .current_dir(&self.config.src),
+        );
+        let actual_hash = recorded
+            .split_whitespace()
+            .nth(2)
+            .unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
 
-            // update_submodule
-            if actual_hash == checked_out_hash.trim_end() {
-                // already checked out
-                return;
-            }
+        // update_submodule
+        if actual_hash == checked_out_hash.trim_end() {
+            // already checked out
+            return;
         }
 
         println!("Updating submodule {}", relative_path.display());
@@ -723,7 +720,7 @@
     fn std_features(&self, target: TargetSelection) -> String {
         let mut features = "panic-unwind".to_string();
 
-        match self.config.llvm_libunwind {
+        match self.config.llvm_libunwind(target) {
             LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"),
             LlvmLibunwind::System => features.push_str(" system-llvm-libunwind"),
             LlvmLibunwind::No => {}
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 3b30e6d..2f4d07d 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -656,7 +656,6 @@
 pub struct LldWrapper {
     pub compiler: Compiler,
     pub target: TargetSelection,
-    pub flavor_feature: &'static str,
 }
 
 impl Step for LldWrapper {
@@ -676,7 +675,7 @@
                 path: "src/tools/lld-wrapper",
                 is_optional_tool: false,
                 source_type: SourceType::InTree,
-                extra_features: vec![self.flavor_feature.to_owned()],
+                extra_features: Vec::new(),
             })
             .expect("expected to build -- essential tool");
 
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 5e6716b..ab6c888 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -98,8 +98,8 @@
 RUN ./build-clang.sh
 ENV CC=clang CXX=clang++
 
-# rustc-perf version from 2022-04-05
-ENV PERF_COMMIT 04fccd80396f954b339c366e30221f4bd52c5e03
+# rustc-perf version from 2022-05-18
+ENV PERF_COMMIT f66cc8f3e04392b0e2fd811f21fd1ece6ebaded3
 RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
     unzip perf.zip && \
     mv rustc-perf-$PERF_COMMIT rustc-perf && \
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
index aedfe98..9b72794 100755
--- a/src/ci/pgo.sh
+++ b/src/ci/pgo.sh
@@ -1,4 +1,5 @@
 #!/bin/bash
+# ignore-tidy-linelength
 
 set -euxo pipefail
 
@@ -87,7 +88,7 @@
 # That's why we override the profile path to include the PID. This will produce many more profiling
 # files, but the resulting profile will produce a slightly faster rustc binary.
 LLVM_PROFILE_FILE=/tmp/rustc-pgo/default_%m_%p.profraw gather_profiles "Check,Debug,Opt" "All" \
-  "externs,ctfe-stress-4,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress"
+"externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
 
 # Merge the profile data we gathered
 ./build/$PGO_HOST/llvm/bin/llvm-profdata \
diff --git a/src/doc/book b/src/doc/book
index d9415b7..b4dd5f0 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit d9415b7cbfcb4b24062683f429bd0ff535396362
+Subproject commit b4dd5f00b87190ad5ef42cbc2a88a783c6ae57ef
diff --git a/src/doc/reference b/src/doc/reference
index 8e36971..b74825d 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 8e36971959ff238b5aa2575fbc7a2e09e1313e82
+Subproject commit b74825d8f88b685e239ade00f00de68ba4cd63d4
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index e9f93cf..2ed2686 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit e9f93cfcf410bc092c9107b8a41a82f144c761f2
+Subproject commit 2ed26865e8c29ef939dc913a97bd321cadd72a9a
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 0c02acd..554c00e 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 0c02acdb6f48f03907a02ea8e537c3272b4fde9f
+Subproject commit 554c00e4805df7f7bffac7db408437d62d6dfb9a
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 0495cd9..03ceb63 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -11,7 +11,7 @@
 askama = { version = "0.11", default-features = false, features = ["config"] }
 atty = "0.2"
 pulldown-cmark = { version = "0.9", default-features = false }
-minifier = "0.0.43"
+minifier = "0.1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 smallvec = "1.6.1"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 27fb470..79d7c41 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -643,11 +643,11 @@
     /// both for visual consistency between 'rustdoc' runs, and to
     /// make writing tests much easier
     #[inline]
-    fn sort_where_predicates(&self, mut predicates: &mut Vec<WherePredicate>) {
+    fn sort_where_predicates(&self, predicates: &mut Vec<WherePredicate>) {
         // We should never have identical bounds - and if we do,
         // they're visually identical as well. Therefore, using
         // an unstable sort is fine.
-        self.unstable_debug_sort(&mut predicates);
+        self.unstable_debug_sort(predicates);
     }
 
     /// Ensure that the bounds are in a consistent order. The precise
@@ -656,11 +656,11 @@
     /// both for visual consistency between 'rustdoc' runs, and to
     /// make writing tests much easier
     #[inline]
-    fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
+    fn sort_where_bounds(&self, bounds: &mut Vec<GenericBound>) {
         // We should never have identical bounds - and if we do,
         // they're visually identical as well. Therefore, using
         // an unstable sort is fine.
-        self.unstable_debug_sort(&mut bounds);
+        self.unstable_debug_sort(bounds);
     }
 
     /// This might look horrendously hacky, but it's actually not that bad.
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 1ccd6a2..a82abe6 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -218,7 +218,7 @@
     }
 }
 
-fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Function {
+fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> clean::Function {
     let sig = cx.tcx.fn_sig(did);
 
     let predicates = cx.tcx.predicates_of(did);
@@ -236,7 +236,6 @@
 
     clean::Enum {
         generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
-        variants_stripped: false,
         variants: cx.tcx.adt_def(did).variants().iter().map(|v| v.clean(cx)).collect(),
     }
 }
@@ -249,7 +248,6 @@
         struct_type: variant.ctor_kind,
         generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
         fields: variant.fields.iter().map(|x| x.clean(cx)).collect(),
-        fields_stripped: false,
     }
 }
 
@@ -259,7 +257,7 @@
 
     let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
     let fields = variant.fields.iter().map(|x| x.clean(cx)).collect();
-    clean::Union { generics, fields, fields_stripped: false }
+    clean::Union { generics, fields }
 }
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9d5619b..c725cf9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -44,12 +44,12 @@
 pub(crate) use self::types::*;
 pub(crate) use self::utils::{get_auto_trait_and_blanket_impls, krate, register_res};
 
-pub(crate) trait Clean<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> T;
+pub(crate) trait Clean<'tcx, T> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> T;
 }
 
-impl Clean<Item> for DocModule<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let mut items: Vec<Item> = vec![];
         items.extend(
             self.foreigns
@@ -89,14 +89,14 @@
     }
 }
 
-impl Clean<Attributes> for [ast::Attribute] {
+impl<'tcx> Clean<'tcx, Attributes> for [ast::Attribute] {
     fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes {
         Attributes::from_ast(self, None)
     }
 }
 
-impl Clean<Option<GenericBound>> for hir::GenericBound<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<GenericBound> {
+impl<'tcx> Clean<'tcx, Option<GenericBound>> for hir::GenericBound<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<GenericBound> {
         Some(match *self {
             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
             hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
@@ -131,9 +131,9 @@
     }
 }
 
-fn clean_trait_ref_with_bindings(
-    cx: &mut DocContext<'_>,
-    trait_ref: ty::TraitRef<'_>,
+fn clean_trait_ref_with_bindings<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
     bindings: &[TypeBinding],
 ) -> Path {
     let kind = cx.tcx.def_kind(trait_ref.def_id).into();
@@ -148,15 +148,15 @@
     path
 }
 
-impl Clean<Path> for ty::TraitRef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Path {
+impl<'tcx> Clean<'tcx, Path> for ty::TraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
         clean_trait_ref_with_bindings(cx, *self, &[])
     }
 }
 
-fn clean_poly_trait_ref_with_bindings(
-    cx: &mut DocContext<'_>,
-    poly_trait_ref: ty::PolyTraitRef<'_>,
+fn clean_poly_trait_ref_with_bindings<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    poly_trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: &[TypeBinding],
 ) -> GenericBound {
     let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
@@ -182,14 +182,14 @@
     )
 }
 
-impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
+impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
         clean_poly_trait_ref_with_bindings(cx, *self, &[])
     }
 }
 
-impl Clean<Lifetime> for hir::Lifetime {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
+impl<'tcx> Clean<'tcx, Lifetime> for hir::Lifetime {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Lifetime {
         let def = cx.tcx.named_region(self.hir_id);
         if let Some(
             rl::Region::EarlyBound(_, node_id)
@@ -205,8 +205,8 @@
     }
 }
 
-impl Clean<Constant> for hir::ConstArg {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
+impl<'tcx> Clean<'tcx, Constant> for hir::ConstArg {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Constant {
         Constant {
             type_: cx
                 .tcx
@@ -217,7 +217,7 @@
     }
 }
 
-impl Clean<Option<Lifetime>> for ty::Region<'_> {
+impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::Region<'tcx> {
     fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
         match **self {
             ty::ReStatic => Some(Lifetime::statik()),
@@ -239,8 +239,8 @@
     }
 }
 
-impl Clean<Option<WherePredicate>> for hir::WherePredicate<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         if !self.in_where_clause() {
             return None;
         }
@@ -248,7 +248,7 @@
             hir::WherePredicate::BoundPredicate(ref wbp) => {
                 let bound_params = wbp
                     .bound_generic_params
-                    .into_iter()
+                    .iter()
                     .map(|param| {
                         // Higher-ranked params must be lifetimes.
                         // Higher-ranked lifetimes can't have bounds.
@@ -279,8 +279,8 @@
     }
 }
 
-impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'tcx> Clean<'tcx, Option<WherePredicate>> for ty::Predicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         let bound_predicate = self.kind();
         match bound_predicate.skip_binder() {
             ty::PredicateKind::Trait(pred) => bound_predicate.rebind(pred).clean(cx),
@@ -300,8 +300,8 @@
     }
 }
 
-impl<'a> Clean<Option<WherePredicate>> for ty::PolyTraitPredicate<'a> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'tcx> Clean<'tcx, Option<WherePredicate>> for ty::PolyTraitPredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
         if self.skip_binder().constness == ty::BoundConstness::ConstIfConst
             && Some(self.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait()
@@ -318,10 +318,10 @@
     }
 }
 
-impl<'tcx> Clean<Option<WherePredicate>>
+impl<'tcx> Clean<'tcx, Option<WherePredicate>>
     for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
 {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(a, b) = self;
 
         if a.is_empty() && b.is_empty() {
@@ -335,8 +335,10 @@
     }
 }
 
-impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
+impl<'tcx> Clean<'tcx, Option<WherePredicate>>
+    for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>
+{
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(ty, lt) = self;
 
         if lt.is_empty() {
@@ -351,8 +353,8 @@
     }
 }
 
-impl<'tcx> Clean<Term> for ty::Term<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Term {
+impl<'tcx> Clean<'tcx, Term> for ty::Term<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Term {
         match self {
             ty::Term::Ty(ty) => Term::Type(ty.clean(cx)),
             ty::Term::Const(c) => Term::Constant(c.clean(cx)),
@@ -360,8 +362,8 @@
     }
 }
 
-impl<'tcx> Clean<Term> for hir::Term<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Term {
+impl<'tcx> Clean<'tcx, Term> for hir::Term<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Term {
         match self {
             hir::Term::Ty(ty) => Term::Type(ty.clean(cx)),
             hir::Term::Const(c) => {
@@ -372,8 +374,8 @@
     }
 }
 
-impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
+impl<'tcx> Clean<'tcx, WherePredicate> for ty::ProjectionPredicate<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> WherePredicate {
         let ty::ProjectionPredicate { projection_ty, term } = self;
         WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: term.clean(cx) }
     }
@@ -381,7 +383,7 @@
 
 fn clean_projection<'tcx>(
     ty: ty::ProjectionTy<'tcx>,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
     let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
@@ -401,8 +403,8 @@
     }
 }
 
-impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for ty::ProjectionTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         clean_projection(*self, cx, None)
     }
 }
@@ -414,7 +416,10 @@
             .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
 }
 
-fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) -> PathSegment {
+fn projection_to_path_segment<'tcx>(
+    ty: ty::ProjectionTy<'tcx>,
+    cx: &mut DocContext<'tcx>,
+) -> PathSegment {
     let item = cx.tcx.associated_item(ty.item_def_id);
     let generics = cx.tcx.generics_of(ty.item_def_id);
     PathSegment {
@@ -426,8 +431,8 @@
     }
 }
 
-impl Clean<GenericParamDef> for ty::GenericParamDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
+impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             ty::GenericParamDefKind::Lifetime => {
                 (self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
@@ -465,10 +470,10 @@
     }
 }
 
-fn clean_generic_param(
-    cx: &mut DocContext<'_>,
-    generics: Option<&hir::Generics<'_>>,
-    param: &hir::GenericParam<'_>,
+fn clean_generic_param<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    generics: Option<&hir::Generics<'tcx>>,
+    param: &hir::GenericParam<'tcx>,
 ) -> GenericParamDef {
     let (name, kind) = match param.kind {
         hir::GenericParamKind::Lifetime { .. } => {
@@ -520,7 +525,7 @@
                 },
             )
         }
-        hir::GenericParamKind::Const { ref ty, default } => (
+        hir::GenericParamKind::Const { ty, default } => (
             param.name.ident().name,
             GenericParamDefKind::Const {
                 did: cx.tcx.hir().local_def_id(param.hir_id).to_def_id(),
@@ -536,8 +541,8 @@
     GenericParamDef { name, kind }
 }
 
-impl Clean<Generics> for hir::Generics<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
+impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
         // Synthetic type-parameters are inserted after normal ones.
         // In order for normal parameters to be able to refer to synthetic ones,
         // scans them first.
@@ -618,10 +623,10 @@
     }
 }
 
-fn clean_ty_generics(
-    cx: &mut DocContext<'_>,
+fn clean_ty_generics<'tcx>(
+    cx: &mut DocContext<'tcx>,
     gens: &ty::Generics,
-    preds: ty::GenericPredicates<'_>,
+    preds: ty::GenericPredicates<'tcx>,
 ) -> Generics {
     // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
     // since `Clean for ty::Predicate` would consume them.
@@ -784,13 +789,13 @@
     }
 }
 
-fn clean_fn_or_proc_macro(
-    item: &hir::Item<'_>,
-    sig: &hir::FnSig<'_>,
-    generics: &hir::Generics<'_>,
+fn clean_fn_or_proc_macro<'tcx>(
+    item: &hir::Item<'tcx>,
+    sig: &hir::FnSig<'tcx>,
+    generics: &hir::Generics<'tcx>,
     body_id: hir::BodyId,
     name: &mut Symbol,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
     let macro_kind = attrs.iter().find_map(|a| {
@@ -868,10 +873,10 @@
     }
 }
 
-fn clean_function(
-    cx: &mut DocContext<'_>,
-    sig: &hir::FnSig<'_>,
-    generics: &hir::Generics<'_>,
+fn clean_function<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    sig: &hir::FnSig<'tcx>,
+    generics: &hir::Generics<'tcx>,
     body_id: hir::BodyId,
 ) -> Function {
     let (generics, decl) = enter_impl_trait(cx, |cx| {
@@ -884,9 +889,9 @@
     Function { decl, generics }
 }
 
-fn clean_args_from_types_and_names(
-    cx: &mut DocContext<'_>,
-    types: &[hir::Ty<'_>],
+fn clean_args_from_types_and_names<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    types: &[hir::Ty<'tcx>],
     names: &[Ident],
 ) -> Arguments {
     Arguments {
@@ -904,9 +909,9 @@
     }
 }
 
-fn clean_args_from_types_and_body_id(
-    cx: &mut DocContext<'_>,
-    types: &[hir::Ty<'_>],
+fn clean_args_from_types_and_body_id<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    types: &[hir::Ty<'tcx>],
     body_id: hir::BodyId,
 ) -> Arguments {
     let body = cx.tcx.hir().body(body_id);
@@ -924,25 +929,25 @@
     }
 }
 
-fn clean_fn_decl_with_args(
-    cx: &mut DocContext<'_>,
-    decl: &hir::FnDecl<'_>,
+fn clean_fn_decl_with_args<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    decl: &hir::FnDecl<'tcx>,
     args: Arguments,
 ) -> FnDecl {
     FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
 }
 
-fn clean_fn_decl_from_did_and_sig(
-    cx: &mut DocContext<'_>,
+fn clean_fn_decl_from_did_and_sig<'tcx>(
+    cx: &mut DocContext<'tcx>,
     did: Option<DefId>,
-    sig: ty::PolyFnSig<'_>,
+    sig: ty::PolyFnSig<'tcx>,
 ) -> FnDecl {
     let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_names(did)).iter();
 
     // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
     // but shouldn't change any code meaning.
     let output = match sig.skip_binder().output().clean(cx) {
-        Type::Tuple(inner) if inner.len() == 0 => DefaultReturn,
+        Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
         ty => Return(ty),
     };
 
@@ -964,17 +969,17 @@
     }
 }
 
-impl Clean<FnRetTy> for hir::FnRetTy<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnRetTy {
+impl<'tcx> Clean<'tcx, FnRetTy> for hir::FnRetTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> FnRetTy {
         match *self {
-            Self::Return(ref typ) => Return(typ.clean(cx)),
+            Self::Return(typ) => Return(typ.clean(cx)),
             Self::DefaultReturn(..) => DefaultReturn,
         }
     }
 }
 
-impl Clean<bool> for hir::IsAuto {
-    fn clean(&self, _: &mut DocContext<'_>) -> bool {
+impl<'tcx> Clean<'tcx, bool> for hir::IsAuto {
+    fn clean(&self, _: &mut DocContext<'tcx>) -> bool {
         match *self {
             hir::IsAuto::Yes => true,
             hir::IsAuto::No => false,
@@ -982,16 +987,16 @@
     }
 }
 
-impl Clean<Path> for hir::TraitRef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Path {
+impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
         let path = self.path.clean(cx);
         register_res(cx, path.res);
         path
     }
 }
 
-impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
+impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
             generic_params: self
@@ -1003,18 +1008,18 @@
     }
 }
 
-impl Clean<Item> for hir::TraitItem<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::TraitItem<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let local_did = self.def_id.to_def_id();
         cx.with_param_env(local_did, |cx| {
             let inner = match self.kind {
-                hir::TraitItemKind::Const(ref ty, Some(default)) => AssocConstItem(
+                hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
                     ty.clean(cx),
                     ConstantKind::Local { def_id: local_did, body: default },
                 ),
-                hir::TraitItemKind::Const(ref ty, None) => TyAssocConstItem(ty.clean(cx)),
+                hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(ty.clean(cx)),
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                    let m = clean_function(cx, sig, &self.generics, body);
+                    let m = clean_function(cx, sig, self.generics, body);
                     MethodItem(m, None)
                 }
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
@@ -1050,21 +1055,21 @@
     }
 }
 
-impl Clean<Item> for hir::ImplItem<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::ImplItem<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let local_did = self.def_id.to_def_id();
         cx.with_param_env(local_did, |cx| {
             let inner = match self.kind {
-                hir::ImplItemKind::Const(ref ty, expr) => {
+                hir::ImplItemKind::Const(ty, expr) => {
                     let default = ConstantKind::Local { def_id: local_did, body: expr };
                     AssocConstItem(ty.clean(cx), default)
                 }
                 hir::ImplItemKind::Fn(ref sig, body) => {
-                    let m = clean_function(cx, sig, &self.generics, body);
+                    let m = clean_function(cx, sig, self.generics, body);
                     let defaultness = cx.tcx.associated_item(self.def_id).defaultness;
                     MethodItem(m, Some(defaultness))
                 }
-                hir::ImplItemKind::TyAlias(ref hir_ty) => {
+                hir::ImplItemKind::TyAlias(hir_ty) => {
                     let type_ = hir_ty.clean(cx);
                     let generics = self.generics.clean(cx);
                     let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
@@ -1091,8 +1096,8 @@
     }
 }
 
-impl Clean<Item> for ty::AssocItem {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let tcx = cx.tcx;
         let kind = match self.kind {
             ty::AssocKind::Const => {
@@ -1282,12 +1287,12 @@
     }
 }
 
-fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
+fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let hir::TyKind::Path(qpath) = kind else { unreachable!() };
 
     match qpath {
-        hir::QPath::Resolved(None, ref path) => {
+        hir::QPath::Resolved(None, path) => {
             if let Res::Def(DefKind::TyParam, did) = path.res {
                 if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
                     return new_ty;
@@ -1304,7 +1309,7 @@
                 resolve_type(cx, path)
             }
         }
-        hir::QPath::Resolved(Some(ref qself), p) => {
+        hir::QPath::Resolved(Some(qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             if let Some(normalized_value) = normalize(cx, ty) {
@@ -1328,7 +1333,7 @@
                 trait_,
             }
         }
-        hir::QPath::TypeRelative(ref qself, segment) => {
+        hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             let res = match ty.kind() {
                 ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
@@ -1352,7 +1357,10 @@
     }
 }
 
-fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
+fn maybe_expand_private_type_alias<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    path: &hir::Path<'tcx>,
+) -> Option<Type> {
     let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
     // Substitute private type aliases
     let def_id = def_id.as_local()?;
@@ -1435,8 +1443,8 @@
     Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
 }
 
-impl Clean<Type> for hir::Ty<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for hir::Ty<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         use rustc_hir::*;
 
         match self.kind {
@@ -1455,8 +1463,8 @@
                 let lifetime = if elided { None } else { Some(l.clean(cx)) };
                 BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
             }
-            TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
-            TyKind::Array(ref ty, ref length) => {
+            TyKind::Slice(ty) => Slice(box ty.clean(cx)),
+            TyKind::Array(ty, ref length) => {
                 let length = match length {
                     hir::ArrayLen::Infer(_, _) => "_".to_string(),
                     hir::ArrayLen::Body(anon_const) => {
@@ -1491,7 +1499,7 @@
                 let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
                 DynTrait(bounds, lifetime)
             }
-            TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
+            TyKind::BareFn(barefn) => BareFunction(box barefn.clean(cx)),
             // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
             TyKind::Infer | TyKind::Err => Infer,
             TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
@@ -1530,7 +1538,7 @@
     }
 }
 
-fn clean_ty<'tcx>(this: Ty<'tcx>, cx: &mut DocContext<'_>, def_id: Option<DefId>) -> Type {
+fn clean_ty<'tcx>(this: Ty<'tcx>, cx: &mut DocContext<'tcx>, def_id: Option<DefId>) -> Type {
     trace!("cleaning type: {:?}", this);
     let ty = normalize(cx, this).unwrap_or(this);
     match *ty.kind() {
@@ -1715,14 +1723,14 @@
     }
 }
 
-impl<'tcx> Clean<Type> for Ty<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Type {
+impl<'tcx> Clean<'tcx, Type> for Ty<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Type {
         clean_ty(*self, cx, None)
     }
 }
 
-impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
+impl<'tcx> Clean<'tcx, Constant> for ty::Const<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Constant {
         // FIXME: instead of storing the stringified expression, store `self` directly instead.
         Constant {
             type_: self.ty().clean(cx),
@@ -1731,15 +1739,15 @@
     }
 }
 
-impl Clean<Item> for hir::FieldDef<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::FieldDef<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let def_id = cx.tcx.hir().local_def_id(self.hir_id).to_def_id();
         clean_field(def_id, self.ident.name, self.ty.clean(cx), cx)
     }
 }
 
-impl Clean<Item> for ty::FieldDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for ty::FieldDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         clean_field(self.did, self.name, cx.tcx.type_of(self.did).clean(cx), cx)
     }
 }
@@ -1765,7 +1773,7 @@
     }
 }
 
-impl Clean<Visibility> for ty::Visibility {
+impl<'tcx> Clean<'tcx, Visibility> for ty::Visibility {
     fn clean(&self, _cx: &mut DocContext<'_>) -> Visibility {
         match *self {
             ty::Visibility::Public => Visibility::Public,
@@ -1779,24 +1787,23 @@
     }
 }
 
-impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct {
+impl<'tcx> Clean<'tcx, VariantStruct> for rustc_hir::VariantData<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> VariantStruct {
         VariantStruct {
             struct_type: CtorKind::from_hir(self),
             fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
-            fields_stripped: false,
         }
     }
 }
 
-impl Clean<Vec<Item>> for hir::VariantData<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
+impl<'tcx> Clean<'tcx, Vec<Item>> for hir::VariantData<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Vec<Item> {
         self.fields().iter().map(|x| x.clean(cx)).collect()
     }
 }
 
-impl Clean<Item> for ty::VariantDef {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for ty::VariantDef {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let kind = match self.ctor_kind {
             CtorKind::Const => Variant::CLike,
             CtorKind::Fn => {
@@ -1804,7 +1811,6 @@
             }
             CtorKind::Fictive => Variant::Struct(VariantStruct {
                 struct_type: CtorKind::Fictive,
-                fields_stripped: false,
                 fields: self.fields.iter().map(|field| field.clean(cx)).collect(),
             }),
         };
@@ -1815,8 +1821,8 @@
     }
 }
 
-impl Clean<Variant> for hir::VariantData<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
+impl<'tcx> Clean<'tcx, Variant> for hir::VariantData<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Variant {
         match self {
             hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
             hir::VariantData::Tuple(..) => Variant::Tuple(self.clean(cx)),
@@ -1825,14 +1831,14 @@
     }
 }
 
-impl Clean<Path> for hir::Path<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Path {
+impl<'tcx> Clean<'tcx, Path> for hir::Path<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
         Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
     }
 }
 
-impl Clean<GenericArgs> for hir::GenericArgs<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
+impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericArgs {
         if self.parenthesized {
             let output = self.bindings[0].ty().clean(cx);
             let output =
@@ -1860,14 +1866,14 @@
     }
 }
 
-impl Clean<PathSegment> for hir::PathSegment<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
+impl<'tcx> Clean<'tcx, PathSegment> for hir::PathSegment<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> PathSegment {
         PathSegment { name: self.ident.name, args: self.args().clean(cx) }
     }
 }
 
-impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
+impl<'tcx> Clean<'tcx, BareFunctionDecl> for hir::BareFnTy<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
             // NOTE: generics must be cleaned before args
             let generic_params =
@@ -1880,9 +1886,9 @@
     }
 }
 
-fn clean_maybe_renamed_item(
-    cx: &mut DocContext<'_>,
-    item: &hir::Item<'_>,
+fn clean_maybe_renamed_item<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    item: &hir::Item<'tcx>,
     renamed: Option<Symbol>,
 ) -> Vec<Item> {
     use hir::ItemKind;
@@ -1902,7 +1908,7 @@
                 bounds: ty.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
                 generics: ty.generics.clean(cx),
             }),
-            ItemKind::TyAlias(hir_ty, ref generics) => {
+            ItemKind::TyAlias(hir_ty, generics) => {
                 let rustdoc_ty = hir_ty.clean(cx);
                 let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
                 TypedefItem(Typedef {
@@ -1911,29 +1917,26 @@
                     item_type: Some(ty),
                 })
             }
-            ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
+            ItemKind::Enum(ref def, generics) => EnumItem(Enum {
                 variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
                 generics: generics.clean(cx),
-                variants_stripped: false,
             }),
-            ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
+            ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
                 generics: generics.clean(cx),
                 bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
             }),
-            ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
+            ItemKind::Union(ref variant_data, generics) => UnionItem(Union {
                 generics: generics.clean(cx),
                 fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
-                fields_stripped: false,
             }),
-            ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
+            ItemKind::Struct(ref variant_data, generics) => StructItem(Struct {
                 struct_type: CtorKind::from_hir(variant_data),
                 generics: generics.clean(cx),
                 fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
-                fields_stripped: false,
             }),
-            ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
+            ItemKind::Impl(impl_) => return clean_impl(impl_, item.hir_id(), cx),
             // proc macros can have a name set by attributes
-            ItemKind::Fn(ref sig, ref generics, body_id) => {
+            ItemKind::Fn(ref sig, generics, body_id) => {
                 clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
             }
             ItemKind::Macro(ref macro_def, _) => {
@@ -1942,7 +1945,7 @@
                     source: display_macro_source(cx, name, macro_def, def_id, ty_vis),
                 })
             }
-            ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
+            ItemKind::Trait(is_auto, unsafety, generics, bounds, item_ids) => {
                 let items =
                     item_ids.iter().map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)).collect();
                 TraitItem(Trait {
@@ -1966,8 +1969,8 @@
     })
 }
 
-impl Clean<Item> for hir::Variant<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
+impl<'tcx> Clean<'tcx, Item> for hir::Variant<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
         let kind = VariantItem(self.data.clean(cx));
         let what_rustc_thinks =
             Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
@@ -1976,7 +1979,11 @@
     }
 }
 
-fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
+fn clean_impl<'tcx>(
+    impl_: &hir::Impl<'tcx>,
+    hir_id: hir::HirId,
+    cx: &mut DocContext<'tcx>,
+) -> Vec<Item> {
     let tcx = cx.tcx;
     let mut ret = Vec::new();
     let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
@@ -2014,11 +2021,11 @@
     ret
 }
 
-fn clean_extern_crate(
-    krate: &hir::Item<'_>,
+fn clean_extern_crate<'tcx>(
+    krate: &hir::Item<'tcx>,
     name: Symbol,
     orig_name: Option<Symbol>,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> Vec<Item> {
     // this is the ID of the `extern crate` statement
     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
@@ -2064,12 +2071,12 @@
     }]
 }
 
-fn clean_use_statement(
-    import: &hir::Item<'_>,
+fn clean_use_statement<'tcx>(
+    import: &hir::Item<'tcx>,
     name: Symbol,
-    path: &hir::Path<'_>,
+    path: &hir::Path<'tcx>,
     kind: hir::UseKind,
-    cx: &mut DocContext<'_>,
+    cx: &mut DocContext<'tcx>,
 ) -> Vec<Item> {
     // We need this comparison because some imports (for std types for example)
     // are "inserted" as well but directly by the compiler and they should not be
@@ -2177,15 +2184,15 @@
     vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
 }
 
-fn clean_maybe_renamed_foreign_item(
-    cx: &mut DocContext<'_>,
-    item: &hir::ForeignItem<'_>,
+fn clean_maybe_renamed_foreign_item<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    item: &hir::ForeignItem<'tcx>,
     renamed: Option<Symbol>,
 ) -> Item {
     let def_id = item.def_id.to_def_id();
     cx.with_param_env(def_id, |cx| {
         let kind = match item.kind {
-            hir::ForeignItemKind::Fn(decl, names, ref generics) => {
+            hir::ForeignItemKind::Fn(decl, names, generics) => {
                 let (generics, decl) = enter_impl_trait(cx, |cx| {
                     // NOTE: generics must be cleaned before args
                     let generics = generics.clean(cx);
@@ -2195,7 +2202,7 @@
                 });
                 ForeignFunctionItem(Function { decl, generics })
             }
-            hir::ForeignItemKind::Static(ref ty, mutability) => {
+            hir::ForeignItemKind::Static(ty, mutability) => {
                 ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
             }
             hir::ForeignItemKind::Type => ForeignTypeItem,
@@ -2210,8 +2217,8 @@
     })
 }
 
-impl Clean<TypeBinding> for hir::TypeBinding<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
+impl<'tcx> Clean<'tcx, TypeBinding> for hir::TypeBinding<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBinding {
         TypeBinding {
             assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) },
             kind: self.kind.clean(cx),
@@ -2219,13 +2226,13 @@
     }
 }
 
-impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
+impl<'tcx> Clean<'tcx, TypeBindingKind> for hir::TypeBindingKind<'tcx> {
+    fn clean(&self, cx: &mut DocContext<'tcx>) -> TypeBindingKind {
         match *self {
             hir::TypeBindingKind::Equality { ref term } => {
                 TypeBindingKind::Equality { term: term.clean(cx) }
             }
-            hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint {
+            hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
                 bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
             },
         }
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index a9c0fe6..f7700c4 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -171,7 +171,7 @@
         if state != Start && needs_space {
             printer.space();
         }
-        print_tt(printer, &tt);
+        print_tt(printer, tt);
         state = next_state;
     }
 }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1bb0219..e10c619 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -619,11 +619,12 @@
             _ => false,
         }
     }
-    pub(crate) fn has_stripped_fields(&self) -> Option<bool> {
+    pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
         match *self.kind {
-            StructItem(ref _struct) => Some(_struct.fields_stripped),
-            UnionItem(ref union) => Some(union.fields_stripped),
-            VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
+            StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
+            UnionItem(ref union_) => Some(union_.has_stripped_entries()),
+            EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
+            VariantItem(ref v) => v.has_stripped_entries(),
             _ => None,
         }
     }
@@ -879,7 +880,7 @@
             let mut doc_cfg = self
                 .iter()
                 .filter(|attr| attr.has_name(sym::doc))
-                .flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
+                .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
                 .filter(|attr| attr.has_name(sym::cfg))
                 .peekable();
             if doc_cfg.peek().is_some() && doc_cfg_active {
@@ -1010,7 +1011,7 @@
 fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
     let s = frag.doc.as_str();
     let mut iter = s.lines();
-    if s == "" {
+    if s.is_empty() {
         out.push('\n');
         return;
     }
@@ -1593,17 +1594,17 @@
         match (self, other) {
             // Recursive cases.
             (Type::Tuple(a), Type::Tuple(b)) => {
-                a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(&b, cache))
+                a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_same(b, cache))
             }
-            (Type::Slice(a), Type::Slice(b)) => a.is_same(&b, cache),
-            (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(&b, cache),
+            (Type::Slice(a), Type::Slice(b)) => a.is_same(b, cache),
+            (Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_same(b, cache),
             (Type::RawPointer(mutability, type_), Type::RawPointer(b_mutability, b_type_)) => {
-                mutability == b_mutability && type_.is_same(&b_type_, cache)
+                mutability == b_mutability && type_.is_same(b_type_, cache)
             }
             (
                 Type::BorrowedRef { mutability, type_, .. },
                 Type::BorrowedRef { mutability: b_mutability, type_: b_type_, .. },
-            ) => mutability == b_mutability && type_.is_same(&b_type_, cache),
+            ) => mutability == b_mutability && type_.is_same(b_type_, cache),
             // Placeholders and generics are equal to all other types.
             (Type::Infer, _) | (_, Type::Infer) => true,
             (Type::Generic(_), _) | (_, Type::Generic(_)) => true,
@@ -1666,7 +1667,7 @@
 
     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
         if let QPath { self_type, trait_, assoc, .. } = self {
-            Some((&self_type, trait_.def_id(), *assoc.clone()))
+            Some((self_type, trait_.def_id(), *assoc.clone()))
         } else {
             None
         }
@@ -2028,14 +2029,24 @@
     pub(crate) struct_type: CtorKind,
     pub(crate) generics: Generics,
     pub(crate) fields: Vec<Item>,
-    pub(crate) fields_stripped: bool,
+}
+
+impl Struct {
+    pub(crate) fn has_stripped_entries(&self) -> bool {
+        self.fields.iter().any(|f| f.is_stripped())
+    }
 }
 
 #[derive(Clone, Debug)]
 pub(crate) struct Union {
     pub(crate) generics: Generics,
     pub(crate) fields: Vec<Item>,
-    pub(crate) fields_stripped: bool,
+}
+
+impl Union {
+    pub(crate) fn has_stripped_entries(&self) -> bool {
+        self.fields.iter().any(|f| f.is_stripped())
+    }
 }
 
 /// This is a more limited form of the standard Struct, different in that
@@ -2045,14 +2056,28 @@
 pub(crate) struct VariantStruct {
     pub(crate) struct_type: CtorKind,
     pub(crate) fields: Vec<Item>,
-    pub(crate) fields_stripped: bool,
+}
+
+impl VariantStruct {
+    pub(crate) fn has_stripped_entries(&self) -> bool {
+        self.fields.iter().any(|f| f.is_stripped())
+    }
 }
 
 #[derive(Clone, Debug)]
 pub(crate) struct Enum {
     pub(crate) variants: IndexVec<VariantIdx, Item>,
     pub(crate) generics: Generics,
-    pub(crate) variants_stripped: bool,
+}
+
+impl Enum {
+    pub(crate) fn has_stripped_entries(&self) -> bool {
+        self.variants.iter().any(|f| f.is_stripped())
+    }
+
+    pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
+        self.variants.iter().filter(|v| !v.is_stripped())
+    }
 }
 
 #[derive(Clone, Debug)]
@@ -2062,6 +2087,15 @@
     Struct(VariantStruct),
 }
 
+impl Variant {
+    pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
+        match *self {
+            Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()),
+            Self::CLike | Self::Tuple(_) => None,
+        }
+    }
+}
+
 /// Small wrapper around [`rustc_span::Span`] that adds helper methods
 /// and enforces calling [`rustc_span::Span::source_callsite()`].
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 47597e0..caea254 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -75,9 +75,9 @@
     Crate { module, primitives, external_traits: cx.external_traits.clone() }
 }
 
-pub(crate) fn substs_to_args(
-    cx: &mut DocContext<'_>,
-    substs: &[ty::subst::GenericArg<'_>],
+pub(crate) fn substs_to_args<'tcx>(
+    cx: &mut DocContext<'tcx>,
+    substs: &[ty::subst::GenericArg<'tcx>],
     mut skip_first: bool,
 ) -> Vec<GenericArg> {
     let mut ret_val =
@@ -99,14 +99,14 @@
     ret_val
 }
 
-fn external_generic_args(
-    cx: &mut DocContext<'_>,
+fn external_generic_args<'tcx>(
+    cx: &mut DocContext<'tcx>,
     did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
+    substs: SubstsRef<'tcx>,
 ) -> GenericArgs {
-    let args = substs_to_args(cx, &substs, has_self);
+    let args = substs_to_args(cx, substs, has_self);
 
     if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
         let inputs =
@@ -127,12 +127,12 @@
     }
 }
 
-pub(super) fn external_path(
-    cx: &mut DocContext<'_>,
+pub(super) fn external_path<'tcx>(
+    cx: &mut DocContext<'tcx>,
     did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
-    substs: SubstsRef<'_>,
+    substs: SubstsRef<'tcx>,
 ) -> Path {
     let def_kind = cx.tcx.def_kind(did);
     let name = cx.tcx.item_name(did);
@@ -439,9 +439,9 @@
     }
 }
 
-pub(crate) fn enter_impl_trait<F, R>(cx: &mut DocContext<'_>, f: F) -> R
+pub(crate) fn enter_impl_trait<'tcx, F, R>(cx: &mut DocContext<'tcx>, f: F) -> R
 where
-    F: FnOnce(&mut DocContext<'_>) -> R,
+    F: FnOnce(&mut DocContext<'tcx>) -> R,
 {
     let old_bounds = mem::take(&mut cx.impl_trait_bounds);
     let r = f(cx);
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index b934a1a..e593243 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -667,7 +667,7 @@
             return Err(1);
         }
 
-        let scrape_examples_options = ScrapeExamplesOptions::new(&matches, &diag)?;
+        let scrape_examples_options = ScrapeExamplesOptions::new(matches, &diag)?;
         let with_examples = matches.opt_strs("with-examples");
         let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?;
 
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 3005bd9..a4ec405 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -228,7 +228,7 @@
     let test_attrs: Vec<_> = attrs
         .iter()
         .filter(|a| a.has_name(sym::doc))
-        .flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new))
+        .flat_map(|a| a.meta_item_list().unwrap_or_default())
         .filter(|a| a.has_name(sym::test))
         .collect();
     let attrs = test_attrs.iter().flat_map(|a| a.meta_item_list().unwrap_or(&[]));
@@ -738,7 +738,7 @@
             }
         };
         // If a parsing error happened, it's very likely that the attribute is incomplete.
-        if !parser.parse_attribute(InnerAttrPolicy::Permitted).is_ok() {
+        if parser.parse_attribute(InnerAttrPolicy::Permitted).is_err() {
             return false;
         }
         // We now check if there is an unclosed delimiter for the attribute. To do so, we look at
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index f3e075b..3364489 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -18,30 +18,15 @@
             StrippedItem(..) => unreachable!(),
             ModuleItem(i) => ModuleItem(self.fold_mod(i)),
             StructItem(mut i) => {
-                let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                if !i.fields_stripped {
-                    i.fields_stripped =
-                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
-                }
                 StructItem(i)
             }
             UnionItem(mut i) => {
-                let num_fields = i.fields.len();
                 i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                if !i.fields_stripped {
-                    i.fields_stripped =
-                        num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
-                }
                 UnionItem(i)
             }
             EnumItem(mut i) => {
-                let num_variants = i.variants.len();
                 i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                if !i.variants_stripped {
-                    i.variants_stripped = num_variants != i.variants.len()
-                        || i.variants.iter().any(|f| f.is_stripped());
-                }
                 EnumItem(i)
             }
             TraitItem(mut i) => {
@@ -54,12 +39,7 @@
             }
             VariantItem(i) => match i {
                 Variant::Struct(mut j) => {
-                    let num_fields = j.fields.len();
                     j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
-                    if !j.fields_stripped {
-                        j.fields_stripped = num_fields != j.fields.len()
-                            || j.fields.iter().any(|f| f.is_stripped());
-                    }
                     VariantItem(Variant::Struct(j))
                 }
                 Variant::Tuple(fields) => {
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index f5c0b5e..09aa042 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -456,7 +456,7 @@
                         let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).kind() &&
                         adt.is_fundamental() {
                         for ty in generics {
-                            if let Some(did) = ty.def_id(&self.cache) {
+                            if let Some(did) = ty.def_id(self.cache) {
                                 dids.insert(did);
                             }
                         }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index da32d8c..3094683 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -5,6 +5,7 @@
 //! assume that HTML output is desired, although it may be possible to redesign
 //! them in the future to instead emit any format desired.
 
+use std::borrow::Cow;
 use std::cell::Cell;
 use std::fmt;
 use std::iter;
@@ -545,10 +546,10 @@
 // Panics if `syms` is empty.
 pub(crate) fn join_with_double_colon(syms: &[Symbol]) -> String {
     let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len()));
-    s.push_str(&syms[0].as_str());
+    s.push_str(syms[0].as_str());
     for sym in &syms[1..] {
         s.push_str("::");
-        s.push_str(&sym.as_str());
+        s.push_str(sym.as_str());
     }
     s
 }
@@ -1069,7 +1070,7 @@
                 write!(f, " for ")?;
             }
 
-            if let Some(ref ty) = self.kind.as_blanket_ty() {
+            if let Some(ty) = self.kind.as_blanket_ty() {
                 fmt_type(ty, f, use_absolute, cx)?;
             } else {
                 fmt_type(&self.for_, f, use_absolute, cx)?;
@@ -1295,9 +1296,11 @@
         item_did: ItemId,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        let to_print = match self {
-            clean::Public => "pub ".to_owned(),
-            clean::Inherited => String::new(),
+        use std::fmt::Write as _;
+
+        let to_print: Cow<'static, str> = match self {
+            clean::Public => "pub ".into(),
+            clean::Inherited => "".into(),
             clean::Visibility::Restricted(vis_did) => {
                 // FIXME(camelid): This may not work correctly if `item_did` is a module.
                 //                 However, rustdoc currently never displays a module's
@@ -1305,17 +1308,16 @@
                 let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
 
                 if vis_did.is_crate_root() {
-                    "pub(crate) ".to_owned()
+                    "pub(crate) ".into()
                 } else if parent_module == Some(vis_did) {
                     // `pub(in foo)` where `foo` is the parent module
                     // is the same as no visibility modifier
-                    String::new()
+                    "".into()
                 } else if parent_module
-                    .map(|parent| find_nearest_parent_module(cx.tcx(), parent))
-                    .flatten()
+                    .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
                     == Some(vis_did)
                 {
-                    "pub(super) ".to_owned()
+                    "pub(super) ".into()
                 } else {
                     let path = cx.tcx().def_path(vis_did);
                     debug!("path={:?}", path);
@@ -1325,14 +1327,14 @@
 
                     let mut s = "pub(in ".to_owned();
                     for seg in &path.data[..path.data.len() - 1] {
-                        s.push_str(&format!("{}::", seg.data.get_opt_name().unwrap()));
+                        let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
                     }
-                    s.push_str(&format!("{}) ", anchor));
-                    s
+                    let _ = write!(s, "{}) ", anchor);
+                    s.into()
                 }
             }
         };
-        display_fn(move |f| f.write_str(&to_print))
+        display_fn(move |f| write!(f, "{}", to_print))
     }
 
     /// This function is the same as print_with_space, except that it renders no links.
@@ -1358,9 +1360,7 @@
                     // `pub(in foo)` where `foo` is the parent module
                     // is the same as no visibility modifier
                     String::new()
-                } else if parent_module
-                    .map(|parent| find_nearest_parent_module(tcx, parent))
-                    .flatten()
+                } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent))
                     == Some(vis_did)
                 {
                     "pub(super) ".to_owned()
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 8877f62..9173300 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1023,7 +1023,7 @@
         let Markdown {
             content: md,
             links,
-            mut ids,
+            ids,
             error_codes: codes,
             edition,
             playground,
@@ -1046,7 +1046,7 @@
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        let p = HeadingLinks::new(p, None, &mut ids, heading_offset);
+        let p = HeadingLinks::new(p, None, ids, heading_offset);
         let p = Footnotes::new(p);
         let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
         let p = TableWrapper::new(p);
@@ -1059,7 +1059,7 @@
 
 impl MarkdownWithToc<'_> {
     pub(crate) fn into_string(self) -> String {
-        let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
+        let MarkdownWithToc(md, ids, codes, edition, playground) = self;
 
         let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
@@ -1068,7 +1068,7 @@
         let mut toc = TocBuilder::new();
 
         {
-            let p = HeadingLinks::new(p, Some(&mut toc), &mut ids, HeadingOffset::H1);
+            let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
             let p = Footnotes::new(p);
             let p = TableWrapper::new(p.map(|(ev, _)| ev));
             let p = CodeBlocks::new(p, codes, edition, playground);
@@ -1081,7 +1081,7 @@
 
 impl MarkdownHtml<'_> {
     pub(crate) fn into_string(self) -> String {
-        let MarkdownHtml(md, mut ids, codes, edition, playground) = self;
+        let MarkdownHtml(md, ids, codes, edition, playground) = self;
 
         // This is actually common enough to special-case
         if md.is_empty() {
@@ -1097,7 +1097,7 @@
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        let p = HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1);
+        let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
         let p = Footnotes::new(p);
         let p = TableWrapper::new(p.map(|(ev, _)| ev));
         let p = CodeBlocks::new(p, codes, edition, playground);
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 76377c4..da42733 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -232,18 +232,18 @@
 
                     let mut path = String::new();
                     for name in &names[..names.len() - 1] {
-                        path.push_str(&name.as_str());
+                        path.push_str(name.as_str());
                         path.push('/');
                     }
-                    path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
+                    path.push_str(&item_path(ty, names.last().unwrap().as_str()));
                     match self.shared.redirections {
                         Some(ref redirections) => {
                             let mut current_path = String::new();
                             for name in &self.current {
-                                current_path.push_str(&name.as_str());
+                                current_path.push_str(name.as_str());
                                 current_path.push('/');
                             }
-                            current_path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
+                            current_path.push_str(&item_path(ty, names.last().unwrap().as_str()));
                             redirections.borrow_mut().insert(current_path, path);
                         }
                         None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 0de50c6..3809738 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -840,7 +840,7 @@
     let mut stability = String::new();
 
     if let Some(ver) = stable_version {
-        stability.push_str(&ver.as_str());
+        stability.push_str(ver.as_str());
         title.push_str(&format!("Stable since Rust version {}", ver));
     }
 
@@ -2299,7 +2299,7 @@
                 buf,
                 "foreign-impls",
                 "Implementations on Foreign Types",
-                res.iter().map(|(name, id)| format!("<a href=\"#{}\">{}</a>", id, Escape(&name))),
+                res.iter().map(|(name, id)| format!("<a href=\"#{}\">{}</a>", id, Escape(name))),
             );
         }
     }
@@ -2363,8 +2363,7 @@
     let mut sidebar = Buffer::new();
 
     let mut variants = e
-        .variants
-        .iter()
+        .variants()
         .filter_map(|v| {
             v.name
                 .as_ref()
@@ -2538,6 +2537,8 @@
 }
 
 fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
+    use std::fmt::Write as _;
+
     let mut sidebar = String::new();
 
     let item_sections_in_use: FxHashSet<_> = items
@@ -2555,7 +2556,7 @@
         .map(|it| item_ty_to_section(it.type_()))
         .collect();
     for &sec in ItemSection::ALL.iter().filter(|sec| item_sections_in_use.contains(sec)) {
-        sidebar.push_str(&format!("<li><a href=\"#{}\">{}</a></li>", sec.id(), sec.name()));
+        let _ = write!(sidebar, "<li><a href=\"#{}\">{}</a></li>", sec.id(), sec.name());
     }
 
     if !sidebar.is_empty() {
@@ -2799,7 +2800,7 @@
             hi - lo
         };
 
-        let mut locs = call_locations.into_iter().collect::<Vec<_>>();
+        let mut locs = call_locations.iter().collect::<Vec<_>>();
         locs.sort_by_key(sort_criterion);
         locs
     };
@@ -2843,7 +2844,7 @@
         if it.peek().is_some() {
             write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#);
             it.for_each(|(_, call_data)| {
-                let (url, _) = link_to_loc(&call_data, &call_data.locations[0]);
+                let (url, _) = link_to_loc(call_data, &call_data.locations[0]);
                 write!(
                     w,
                     r#"<li><a href="{url}">{name}</a></li>"#,
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 2c0b8d7..ed41b95 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1136,6 +1136,7 @@
 }
 
 fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
+    let count_variants = e.variants().count();
     wrap_into_docblock(w, |w| {
         wrap_item(w, "enum", |w| {
             render_attributes_in_pre(w, it, "");
@@ -1147,16 +1148,16 @@
                 e.generics.print(cx),
                 print_where_clause(&e.generics, cx, 0, true),
             );
-            if e.variants.is_empty() && !e.variants_stripped {
+            let variants_stripped = e.has_stripped_entries();
+            if count_variants == 0 && !variants_stripped {
                 w.write_str(" {}");
             } else {
                 w.write_str(" {\n");
-                let count_variants = e.variants.len();
                 let toggle = should_hide_fields(count_variants);
                 if toggle {
                     toggle_open(w, format_args!("{} variants", count_variants));
                 }
-                for v in &e.variants {
+                for v in e.variants() {
                     w.write_str("    ");
                     let name = v.name.unwrap();
                     match *v.kind {
@@ -1185,7 +1186,7 @@
                     w.write_str(",\n");
                 }
 
-                if e.variants_stripped {
+                if variants_stripped {
                     w.write_str("    // some variants omitted\n");
                 }
                 if toggle {
@@ -1198,7 +1199,7 @@
 
     document(w, cx, it, None, HeadingOffset::H2);
 
-    if !e.variants.is_empty() {
+    if count_variants != 0 {
         write!(
             w,
             "<h2 id=\"variants\" class=\"variants small-section-header\">\
@@ -1206,7 +1207,7 @@
             document_non_exhaustive_header(it)
         );
         document_non_exhaustive(w, it);
-        for variant in &e.variants {
+        for variant in e.variants() {
             let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
             write!(
                 w,
@@ -1650,7 +1651,7 @@
         }
     }
 
-    if it.has_stripped_fields().unwrap() {
+    if it.has_stripped_entries().unwrap() {
         write!(w, "    /* private fields */\n{}", tab);
     }
     if toggle {
@@ -1706,11 +1707,11 @@
             }
 
             if has_visible_fields {
-                if it.has_stripped_fields().unwrap() {
+                if it.has_stripped_entries().unwrap() {
                     write!(w, "\n{}    /* private fields */", tab);
                 }
                 write!(w, "\n{}", tab);
-            } else if it.has_stripped_fields().unwrap() {
+            } else if it.has_stripped_entries().unwrap() {
                 write!(w, " /* private fields */ ");
             }
             if toggle {
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 4e53ba4..3daef3d 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -37,7 +37,7 @@
                 desc,
                 parent: Some(did),
                 parent_idx: None,
-                search_type: get_function_type_for_search(item, tcx, &cache),
+                search_type: get_function_type_for_search(item, tcx, cache),
                 aliases: item.attrs.get_doc_aliases(),
             });
         }
@@ -182,8 +182,8 @@
         })
         .expect("failed serde conversion")
         // All these `replace` calls are because we have to go through JS string for JSON content.
-        .replace(r#"\"#, r"\\")
-        .replace(r#"'"#, r"\'")
+        .replace('\\', r"\\")
+        .replace('\'', r"\'")
         // We need to escape double quotes for the JSON.
         .replace("\\\"", "\\\\\"")
     )
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 287ce96..86961dc 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -49,7 +49,7 @@
         if generate_link_to_definition {
             tcx.hir().walk_toplevel_module(&mut visitor);
         }
-        let sources = sources::collect_local_sources(tcx, src_root, &krate);
+        let sources = sources::collect_local_sources(tcx, src_root, krate);
         (sources, visitor.matches)
     } else {
         (Default::default(), Default::default())
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index bf96230..7afd09b3 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -47,5 +47,12 @@
             { "beforeColon": false, "afterColon": true, "mode": "strict" }
         ],
         "func-call-spacing": ["error", "never"],
+        "space-infix-ops": "error",
+        "space-before-function-paren": ["error", "never"],
+        "space-before-blocks": "error",
+        "comma-dangle": ["error", "always-multiline"],
+        "comma-style": ["error", "last"],
+        "max-len": ["error", { "code": 100, "tabWidth": 4 }],
+        "eol-last": ["error", "always"],
     }
 };
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 4eb8029..d0229bd 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1415,30 +1415,6 @@
 #settings-menu.rotate > a img {
 	animation: rotating 2s linear infinite;
 }
-#settings-menu #settings {
-	position: absolute;
-	right: 0;
-	z-index: 1;
-	display: block;
-	margin-top: 7px;
-	border-radius: 3px;
-	border: 1px solid;
-}
-#settings-menu #settings .setting-line {
-	margin: 0.6em;
-}
-/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
-#settings-menu #settings::before {
-	content: '';
-	position: absolute;
-	right: 11px;
-	border: solid;
-	border-width: 1px 1px 0 0;
-	display: inline-block;
-	padding: 4px;
-	transform: rotate(-45deg);
-	top: -5px;
-}
 
 #help-button {
 	font-family: "Fira Sans", Arial, sans-serif;
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 0758874..c69ff04 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -46,9 +46,12 @@
 .toggle {
 	position: relative;
 	display: inline-block;
-	width: 45px;
+	width: 100%;
 	height: 27px;
 	margin-right: 20px;
+	display: flex;
+	align-items: center;
+	cursor: pointer;
 }
 
 .toggle input {
@@ -57,12 +60,12 @@
 }
 
 .slider {
-	position: absolute;
+	position: relative;
+	width: 45px;
+	display: block;
+	height: 28px;
+	margin-right: 20px;
 	cursor: pointer;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
 	background-color: #ccc;
 	transition: .3s;
 }
@@ -95,3 +98,28 @@
 	width: 100%;
 	display: block;
 }
+
+div#settings {
+	position: absolute;
+	right: 0;
+	z-index: 1;
+	display: block;
+	margin-top: 7px;
+	border-radius: 3px;
+	border: 1px solid;
+}
+#settings .setting-line {
+	margin: 1.2em 0.6em;
+}
+/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
+div#settings::before {
+	content: '';
+	position: absolute;
+	right: 11px;
+	border: solid;
+	border-width: 1px 1px 0 0;
+	display: inline-block;
+	padding: 4px;
+	transform: rotate(-45deg);
+	top: -5px;
+}
diff --git a/src/librustdoc/html/static/images/brush.svg b/src/librustdoc/html/static/images/brush.svg
deleted file mode 100644
index ea266e8..0000000
--- a/src/librustdoc/html/static/images/brush.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 454c7f55..0fbc2d0 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -63,7 +63,7 @@
     removeClass(document.getElementById(MAIN_ID), "hidden");
 }
 
-(function () {
+(function() {
     window.rootPath = getVar("root-path");
     window.currentCrate = getVar("current-crate");
     window.searchJS =  resourcePath("search", ".js");
@@ -929,7 +929,7 @@
     searchState.setup();
 }());
 
-(function () {
+(function() {
     let reset_button_timeout = null;
 
     window.copy_path = but => {
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 7b9d86a..fd7a144 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -2,7 +2,7 @@
 
 "use strict";
 
-(function () {
+(function() {
     // Number of lines shown when code viewer is not expanded
     const MAX_LINES = 10;
 
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 8770cc3..3d1d942 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -5,7 +5,7 @@
 
 "use strict";
 
-(function () {
+(function() {
     const isSettingsPage = window.location.pathname.endsWith("/settings.html");
 
     function changeSetting(settingName, value) {
@@ -130,12 +130,11 @@
             } else {
                 // This is a toggle.
                 const checked = setting["default"] === true ? " checked" : "";
-                output += `
-                    <label class="toggle">
-                        <input type="checkbox" id="${js_data_name}"${checked}>
-                        <span class="slider"></span>
-                    </label>
-                    <div>${setting_name}</div>`;
+                output += `<label class="toggle">\
+                        <input type="checkbox" id="${js_data_name}"${checked}>\
+                        <span class="slider"></span>\
+                        <span class="label">${setting_name}</span>\
+                    </label>`;
             }
             output += "</div>";
         }
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 15e3bdf..aaac878 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -187,7 +187,7 @@
     }
 }
 
-const handleSourceHighlight = (function () {
+const handleSourceHighlight = (function() {
     let prev_line_id = 0;
 
     const set_fragment = name => {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 3fcf66a..4fcf049 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -4,7 +4,7 @@
 window.currentTheme = document.getElementById("themeStyle");
 window.mainTheme = document.getElementById("mainThemeStyle");
 
-const settingsDataset = (function () {
+const settingsDataset = (function() {
     const settingsElement = document.getElementById("default-settings");
     if (settingsElement === null) {
         return null;
@@ -163,7 +163,7 @@
     }
 }
 
-const updateSystemTheme = (function () {
+const updateSystemTheme = (function() {
     if (!window.matchMedia) {
         // fallback to the CSS computed value
         return () => {
diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs
index 07e3305..a12c2a6 100644
--- a/src/librustdoc/html/toc.rs
+++ b/src/librustdoc/html/toc.rs
@@ -163,15 +163,18 @@
 
 impl Toc {
     fn print_inner(&self, v: &mut String) {
+        use std::fmt::Write as _;
+
         v.push_str("<ul>");
         for entry in &self.entries {
             // recursively format this table of contents
-            v.push_str(&format!(
+            let _ = write!(
+                v,
                 "\n<li><a href=\"#{id}\">{num} {name}</a>",
                 id = entry.id,
                 num = entry.sec_number,
                 name = entry.name
-            ));
+            );
             entry.children.print_inner(&mut *v);
             v.push_str("</li>");
         }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index bc99207..6a8e478 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -249,7 +249,8 @@
 
 impl FromWithTcx<clean::Struct> for Struct {
     fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
-        let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
+        let fields_stripped = struct_.has_stripped_entries();
+        let clean::Struct { struct_type, generics, fields } = struct_;
         Struct {
             struct_type: from_ctor_kind(struct_type),
             generics: generics.into_tcx(tcx),
@@ -261,8 +262,9 @@
 }
 
 impl FromWithTcx<clean::Union> for Union {
-    fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self {
-        let clean::Union { generics, fields, fields_stripped } = struct_;
+    fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self {
+        let fields_stripped = union_.has_stripped_entries();
+        let clean::Union { generics, fields } = union_;
         Union {
             generics: generics.into_tcx(tcx),
             fields_stripped,
@@ -586,7 +588,8 @@
 
 impl FromWithTcx<clean::Enum> for Enum {
     fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
-        let clean::Enum { variants, generics, variants_stripped } = enum_;
+        let variants_stripped = enum_.has_stripped_entries();
+        let clean::Enum { variants, generics } = enum_;
         Enum {
             generics: generics.into_tcx(tcx),
             variants_stripped,
@@ -598,7 +601,8 @@
 
 impl FromWithTcx<clean::VariantStruct> for Struct {
     fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self {
-        let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
+        let fields_stripped = struct_.has_stripped_entries();
+        let clean::VariantStruct { struct_type, fields } = struct_;
         Struct {
             struct_type: from_ctor_kind(struct_type),
             generics: Default::default(),
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 3981d49..4c6e3eb 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -265,7 +265,7 @@
                 self.items.entry(filename).or_default().count_item(
                     has_docs,
                     has_doc_example,
-                    should_have_doc_example(self.ctx, &i),
+                    should_have_doc_example(self.ctx, i),
                     should_have_docs,
                 );
             }
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 8a50938..9cc006b 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -160,7 +160,7 @@
                 sp,
             );
             for code_block in markdown::rust_code_blocks(dox, &extra) {
-                self.check_rust_syntax(&item, dox, code_block);
+                self.check_rust_syntax(item, dox, code_block);
             }
         }
 
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 0fb0c7d..735a077 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -35,9 +35,9 @@
 
 impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
+        let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
 
-        look_for_tests(self.cx, &dox, &item);
+        look_for_tests(self.cx, &dox, item);
 
         self.visit_item_recur(item)
     }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ea0f510..ab57005 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -494,7 +494,7 @@
                     DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Variant,
                     def_id,
                 ) => (Res::from_def_id(self.cx.tcx, self.cx.tcx.parent(def_id)), Some(def_id)),
-                _ => ((res, None)),
+                _ => (res, None),
             });
         } else if ns == MacroNS {
             return Err(UnresolvedPath {
@@ -636,10 +636,9 @@
             Res::Primitive(prim) => {
                 self.resolve_primitive_associated_item(prim, ns, item_name).or_else(|| {
                     self.primitive_type_to_ty(prim)
-                        .map(|ty| {
+                        .and_then(|ty| {
                             resolve_associated_trait_item(ty, module_id, item_name, ns, self.cx)
                         })
-                        .flatten()
                         .map(|item| (root_res, item.def_id))
                 })
             }
@@ -903,7 +902,7 @@
                 tmp_links.insert(doc.clone(), preprocessed_markdown_links(&doc));
             }
             for md_link in &tmp_links[&doc] {
-                let link = self.resolve_link(&item, &doc, parent_node, md_link);
+                let link = self.resolve_link(item, &doc, parent_node, md_link);
                 if let Some(link) = link {
                     self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
                 }
@@ -1136,7 +1135,7 @@
                     let kind = self.cx.tcx.def_kind(id);
                     self.verify_disambiguator(
                         path_str,
-                        &ori_link,
+                        ori_link,
                         kind,
                         id,
                         disambiguator,
@@ -1150,14 +1149,14 @@
                         && item.item_id.is_local()
                         && !self.cx.tcx.features().intra_doc_pointers
                     {
-                        self.report_rawptr_assoc_feature_gate(dox, &ori_link, item);
+                        self.report_rawptr_assoc_feature_gate(dox, ori_link, item);
                     }
                 } else {
                     match disambiguator {
                         Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
                         Some(other) => {
                             self.report_disambiguator_mismatch(
-                                path_str, &ori_link, other, res, &diag_info,
+                                path_str, ori_link, other, res, &diag_info,
                             );
                             return None;
                         }
@@ -1180,7 +1179,7 @@
                     };
                 self.verify_disambiguator(
                     path_str,
-                    &ori_link,
+                    ori_link,
                     kind_for_dis,
                     id_for_dis,
                     disambiguator,
@@ -1274,7 +1273,7 @@
             }
             suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
         };
-        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, callback);
+        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
     }
 
     fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &MarkdownLink, item: &Item) {
@@ -1930,7 +1929,7 @@
     msg: &str,
     anchor_idx: usize,
 ) {
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
         if let Some(mut sp) = sp {
             if let Some((fragment_offset, _)) =
                 diag_info.ori_link.char_indices().filter(|(_, x)| *x == '#').nth(anchor_idx)
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index 3012db0..d8ad299 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -91,11 +91,7 @@
         }
         break;
     }
-    if current_pos == end_pos {
-        return None;
-    } else {
-        return Some(current_pos);
-    }
+    if current_pos == end_pos { None } else { Some(current_pos) }
 }
 
 fn extract_html_tag(
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index ab5526e..533e2ce 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -38,9 +38,16 @@
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         if i.attrs.lists(sym::doc).has_word(sym::hidden) {
             debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
-            // use a dedicated hidden item for given item type if any
+            // Use a dedicated hidden item for fields, variants, and modules.
+            // We need to keep private fields and variants, so that the docs
+            // can show a placeholder "// some variants omitted". We need to keep
+            // private modules, because they can contain impl blocks, and impl
+            // block privacy is inherited from the type and trait, not from the
+            // module it's defined in. Both of these are marked "stripped," and
+            // not included in the final docs, but since they still have an effect
+            // on the final doc, cannot be completely removed from the Clean IR.
             match *i.kind {
-                clean::StructFieldItem(..) | clean::ModuleItem(..) => {
+                clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
                     // We need to recurse into stripped modules to
                     // strip things like impl methods but when doing so
                     // we must not add any items to the `retained` set.
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index fa8be9a..75e1dd4 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -11,7 +11,6 @@
             StrippedItem(..) => unreachable!(),
             ModuleItem(i) => {
                 self.visit_mod(i);
-                return;
             }
             StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
             UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 519ace7..d57868c 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -365,7 +365,7 @@
                     om.items.push((item, renamed));
                 }
             }
-            hir::ItemKind::Impl(ref impl_) => {
+            hir::ItemKind::Impl(impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && impl_.of_trait.is_none() {
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
index e6afbe4..f2c2f47 100644
--- a/src/test/codegen/consts.rs
+++ b/src/test/codegen/consts.rs
@@ -10,7 +10,7 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @alloc12 = {{.*}}, align 2
+// CHECK: @alloc14 = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
index cb4273b..d7636c8 100644
--- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
@@ -16,7 +16,7 @@
   
       bb1: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
-          begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
+          _2 = begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/panic.rs:LL:COL
                                            // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
index 5c42c7d..eb579b5 100644
--- a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
@@ -5,17 +5,15 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inline-diverging.rs:7:12: 7:12
       let mut _1: !;                       // in scope 0 at $DIR/inline-diverging.rs:7:12: 9:2
       let _2: !;                           // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
-+     let mut _3: !;                       // in scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
 +     scope 1 (inlined sleep) {            // at $DIR/inline-diverging.rs:8:5: 8:12
 +     }
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
--         sleep();                         // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
+-         _2 = sleep();                    // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline-diverging.rs:8:5: 8:10
 -                                          // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
-+         StorageLive(_3);                 // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
 +         goto -> bb1;                     // scope 0 at $DIR/inline-diverging.rs:8:5: 8:12
 +     }
 + 
diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
index 31719b4..3ce823a 100644
--- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
@@ -9,8 +9,8 @@
       let mut _4: i32;                     // in scope 0 at $DIR/inline-diverging.rs:14:9: 14:10
       let mut _5: !;                       // in scope 0 at $DIR/inline-diverging.rs:15:12: 17:6
       let _6: !;                           // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
-+     let mut _7: !;                       // in scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
 +     scope 1 (inlined panic) {            // at $DIR/inline-diverging.rs:16:9: 16:16
++         let mut _7: !;                   // in scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
 +     }
   
       bb0: {
@@ -33,9 +33,9 @@
   
       bb2: {
           StorageLive(_6);                 // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
--         panic();                         // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
-+         StorageLive(_7);                 // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
-+         begin_panic::<&str>(const "explicit panic"); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
+-         _6 = panic();                    // scope 0 at $DIR/inline-diverging.rs:16:9: 16:16
++         StorageLive(_7);                 // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
++         _7 = begin_panic::<&str>(const "explicit panic"); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-diverging.rs:16:9: 16:14
 -                                          // + literal: Const { ty: fn() -> ! {panic}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
index 3b890e4..647c27d 100644
--- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -4,22 +4,21 @@
   fn h() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
       let _1: (!, !);                      // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+     let mut _2: (!, !);                  // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+     let mut _3: fn() -> ! {sleep};       // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+     let mut _10: ();                     // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
-+     let mut _11: ();                     // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
++     let mut _2: fn() -> ! {sleep};       // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++     let mut _9: ();                      // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
++     let mut _10: ();                     // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
-+         debug f => _3;                   // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
-+         let _4: !;                       // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+         let mut _5: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         let mut _7: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
-+         let mut _8: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
-+         let mut _9: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
++         debug f => _2;                   // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
++         let _3: !;                       // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         let mut _4: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         let mut _6: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
++         let mut _7: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
++         let mut _8: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
 +         scope 2 {
-+             debug a => _4;               // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
-+             let _6: !;                   // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
++             debug a => _3;               // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
++             let _5: !;                   // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
 +             scope 3 {
-+                 debug b => _6;           // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
++                 debug b => _5;           // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
 +             }
 +             scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
 +                 scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -34,21 +33,20 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
--         call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
+-         _1 = call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
 +         StorageLive(_2);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+         StorageLive(_3);                 // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+         _3 = sleep;                      // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++         _2 = sleep;                      // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
                                            // mir::Constant
 -                                          // + span: $DIR/inline-diverging.rs:22:5: 22:15
 -                                          // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) }
 -                                          // mir::Constant
                                            // + span: $DIR/inline-diverging.rs:22:16: 22:21
                                            // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
-+         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+         StorageLive(_5);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         _5 = &_3;                        // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+         StorageLive(_10);                // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
-+         _10 = const ();                  // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         StorageLive(_3);                 // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         _4 = &_2;                        // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         StorageLive(_9);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         _9 = const ();                   // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
 +         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
 +     }
 + 
diff --git a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
index 7e966b2..899c846 100644
--- a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
@@ -21,7 +21,7 @@
         StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
         StorageLive(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
         _3 = ();                         // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
-        transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
+        _2 = transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
                                          // mir::Constant
                                          // + span: $DIR/issue-72181-1.rs:17:9: 17:40
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
@@ -34,7 +34,7 @@
         StorageLive(_4);                 // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
         StorageLive(_5);                 // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
         _5 = move _2;                    // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
-        f(move _5) -> bb4;               // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
+        _4 = f(move _5) -> bb4;          // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
                                          // mir::Constant
                                          // + span: $DIR/issue-72181-1.rs:20:5: 20:6
                                          // + literal: Const { ty: fn(Void) -> ! {f}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index 288250e..4426cd8 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -13,11 +13,12 @@
       let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _12: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _13: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _16: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _17: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _17: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _18: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
@@ -25,7 +26,7 @@
               debug _prev => _4;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
               let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               let _10: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _20: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let mut _21: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
                   debug left_val => _9;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _10;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -62,11 +63,11 @@
           StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _7 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-          _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _8 = _21;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_6);                      // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -93,16 +94,17 @@
           discriminant(_14) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _16 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _15 = _16;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _17 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _16 = _17;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _17 = _18;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_19);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_19) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _18 = _19;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_20);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_20);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_20) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _16, move _18, move _20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index 288250e..4426cd8 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -13,11 +13,12 @@
       let mut _11: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _12: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       let mut _13: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _16: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _17: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _18: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: !;                          // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _17: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _18: &i32;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _19: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _20: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       scope 1 {
           debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
@@ -25,7 +26,7 @@
               debug _prev => _4;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
               let _9: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               let _10: &i32;               // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let mut _20: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+              let mut _21: &i32;           // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
                   debug left_val => _9;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   debug right_val => _10;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -62,11 +63,11 @@
           StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _7 = &_1;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_8);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = const main::promoted[0];   // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-          _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _8 = _21;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_6);                      // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -93,16 +94,17 @@
           discriminant(_14) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _16 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _15 = _16;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_17);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _17 = _9;                        // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _16 = _17;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _18 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _17 = _18;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageLive(_19);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          Deinit(_19);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          discriminant(_19) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = _10;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _18 = _19;                       // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_20);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          Deinit(_20);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          discriminant(_20) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _16, move _18, move _20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index 89c7154..c96a664 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
@@ -132,7 +132,7 @@
           StorageLive(_27);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_27);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           discriminant(_27) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index 89c7154..c96a664 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
@@ -132,7 +132,7 @@
           StorageLive(_27);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_27);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           discriminant(_27) = 0;           // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _21 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index f9e1143..29bcef2 100644
--- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -67,7 +67,7 @@
   
       bb1: {
           StorageLive(_22);                // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
-          core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
+          _22 = core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/panic.rs:LL:COL
                                            // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index a617417..1e6da38 100644
--- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -7,7 +7,7 @@
     let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
     let mut _4: char;                    // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
     let mut _5: u32;                     // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
-    let mut _11: isize;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+    let mut _12: isize;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
         debug self => _2;                // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         debug radix => _5;               // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
@@ -22,6 +22,7 @@
     scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
         debug self => _3;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _10: isize;              // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        let mut _11: !;                  // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 4 {
             debug val => _0;             // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
         }
@@ -43,7 +44,7 @@
     }
 
     bb1: {
-        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_12);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
         StorageLive(_3);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
         StorageLive(_4);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
         _4 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
@@ -61,7 +62,7 @@
     }
 
     bb3: {
-        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_12);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
         _0 = const 0_u32;                // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
         goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
     }
@@ -75,18 +76,19 @@
         StorageDead(_8);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageLive(_9);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         _9 = discriminant((*_6));        // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        _11 = move _9;                   // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        _12 = move _9;                   // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_9);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_6);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_7);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
         StorageDead(_2);                 // scope 0 at $DIR/issue-59352.rs:14:22: 14:23
-        switchInt(move _11) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        switchInt(move _12) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
     }
 
     bb6: {
-        core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/option.rs:LL:COL
                                          // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index 50711f5..eb463af 100644
--- a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:29:5: 29:47
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
--         std::intrinsics::unreachable();  // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
+-         _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
index 2044d34..8a297ce 100644
--- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
@@ -20,7 +20,7 @@
 
     bb1: {
         StorageLive(_4);                 // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
-        begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
+        _4 = begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/std/src/panic.rs:LL:COL
                                          // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index 5c2a7e2..69742d6 100644
--- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -171,7 +171,7 @@
         Retag(_32);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_34);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _34 = Option::<Arguments>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        _28 = core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                          // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<usize, usize>}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index 9a9c45a..1b2d1e3 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -34,7 +34,7 @@
 
 // We check that the "Use system theme" is disabled.
 assert-property: ("#use-system-theme", {"checked": "false"})
-assert: "//*[@class='setting-line']/*[text()='Use system theme']"
+assert: "//*[@class='setting-line']//span[text()='Use system theme']"
 // Meaning that only the "theme" menu is showing up.
 assert: ".setting-line:not(.hidden) #theme"
 assert: ".setting-line.hidden #preferred-dark-theme"
@@ -55,7 +55,13 @@
 assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
 assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme")
 
+// We now check that clicking on the "sliders"' text is like clicking on the slider.
+// To test it, we use the "Disable keyboard shortcuts".
+local-storage: {"rustdoc-disable-shortcuts": "false"}
+click: ".setting-line:last-child .toggle .label"
+assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
+
 // Now we go to the settings page to check that the CSS is loaded as expected.
 goto: file://|DOC_PATH|/settings.html
 wait-for: "#settings"
-assert-css: (".setting-line .toggle", {"width": "45px", "margin-right": "20px"})
+assert-css: (".setting-line .toggle .slider", {"width": "45px", "margin-right": "20px"})
diff --git a/src/test/rustdoc/strip-enum-variant.no-not-shown.html b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
new file mode 100644
index 0000000..c4ee1a9
--- /dev/null
+++ b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
@@ -0,0 +1 @@
+<ul><li><a href="#variant.Shown">Shown</a></li></ul>
\ No newline at end of file
diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs
index 12e5761..f82ffdf 100644
--- a/src/test/rustdoc/strip-enum-variant.rs
+++ b/src/test/rustdoc/strip-enum-variant.rs
@@ -2,6 +2,8 @@
 // @has - '//code' 'Shown'
 // @!has - '//code' 'NotShown'
 // @has - '//code' '// some variants omitted'
+// Also check that `NotShown` isn't displayed in the sidebar.
+// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]/ul'
 pub enum MyThing {
     Shown,
     #[doc(hidden)]
diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr
index 513f70d..af9b8de 100644
--- a/src/test/ui-fulldeps/lint-tool-test.stderr
+++ b/src/test/ui-fulldeps/lint-tool-test.stderr
@@ -18,14 +18,6 @@
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
-warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:36:8
-   |
-LL | #[deny(this_lint_does_not_exist)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(unknown_lints)]` on by default
-
 warning: lint name `test_lint` is deprecated and may not have an effect in the future.
   --> $DIR/lint-tool-test.rs:9:23
    |
@@ -44,6 +36,14 @@
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
+warning: unknown lint: `this_lint_does_not_exist`
+  --> $DIR/lint-tool-test.rs:36:8
+   |
+LL | #[deny(this_lint_does_not_exist)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unknown_lints)]` on by default
+
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-tool-test.rs:6:1
    |
diff --git a/src/test/ui/cast/casts-issue-46365.rs b/src/test/ui/cast/casts-issue-46365.rs
index 3d0fea2..a2205b7 100644
--- a/src/test/ui/cast/casts-issue-46365.rs
+++ b/src/test/ui/cast/casts-issue-46365.rs
@@ -3,5 +3,5 @@
 }
 
 fn main() {
-    let _foo: *mut Lorem = core::ptr::null_mut(); // no error here
+    let _foo: *mut Lorem = core::ptr::NonNull::dangling().as_ptr(); // no error here
 }
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.rs b/src/test/ui/cfg/cfg-target-compact-errors.rs
new file mode 100644
index 0000000..bca2275
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.rs
@@ -0,0 +1,17 @@
+// check-fail
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(o::o))]
+//~^ ERROR `cfg` predicate key must be an identifier
+fn one() {}
+
+#[cfg(target(os = 8))]
+//~^ ERROR literal in `cfg` predicate value must be a string
+fn two() {}
+
+#[cfg(target(os = "linux", pointer(width = "64")))]
+//~^ ERROR invalid predicate `target_pointer`
+fn three() {}
+
+fn main() {}
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.stderr b/src/test/ui/cfg/cfg-target-compact-errors.stderr
new file mode 100644
index 0000000..bb85830
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.stderr
@@ -0,0 +1,22 @@
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-target-compact-errors.rs:5:14
+   |
+LL | #[cfg(target(o::o))]
+   |              ^^^^
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-target-compact-errors.rs:9:19
+   |
+LL | #[cfg(target(os = 8))]
+   |                   ^
+
+error[E0537]: invalid predicate `target_pointer`
+  --> $DIR/cfg-target-compact-errors.rs:13:28
+   |
+LL | #[cfg(target(os = "linux", pointer(width = "64")))]
+   |                            ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0537, E0565.
+For more information about an error, try `rustc --explain E0537`.
diff --git a/src/test/ui/cfg/cfg-target-compact.rs b/src/test/ui/cfg/cfg-target-compact.rs
new file mode 100644
index 0000000..dc95a80
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact.rs
@@ -0,0 +1,10 @@
+// run-pass
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", pointer_width = "64"))]
+pub fn main() {
+}
+
+#[cfg(not(target(os = "linux", pointer_width = "64")))]
+pub fn main() {
+}
diff --git a/src/test/ui/check-cfg/compact-names.rs b/src/test/ui/check-cfg/compact-names.rs
new file mode 100644
index 0000000..bff8074
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", architecture = "arm"))]
+//~^ WARNING unexpected `cfg` condition name
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-names.stderr b/src/test/ui/check-cfg/compact-names.stderr
new file mode 100644
index 0000000..f1fc428
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/compact-names.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", architecture = "arm"))]
+   |                            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/compact-values.rs b/src/test/ui/check-cfg/compact-values.rs
new file mode 100644
index 0000000..1f17057
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=values() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", arch = "X"))]
+//~^ WARNING unexpected `cfg` condition value
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr
new file mode 100644
index 0000000..a196e15
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/compact-values.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", arch = "X"))]
+   |                            ^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
new file mode 100644
index 0000000..4cd86fe
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
@@ -0,0 +1,39 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/dependence_lint.rs:13:32
+   |
+LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
+   |                                ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/dependence_lint.rs:20:37
+   |
+LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
+   |                                     ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+warning: cannot use constants which depend on generic parameters in types
+  --> $DIR/dependence_lint.rs:9:9
+   |
+LL |     [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(const_evaluatable_unchecked)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+warning: cannot use constants which depend on generic parameters in types
+  --> $DIR/dependence_lint.rs:16:9
+   |
+LL |     [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
new file mode 100644
index 0000000..b13bcdb
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
@@ -0,0 +1,34 @@
+error: overly complex generic constant
+  --> $DIR/dependence_lint.rs:16:9
+   |
+LL |     [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: overly complex generic constant
+  --> $DIR/dependence_lint.rs:20:17
+   |
+LL |     let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: unconstrained generic constant
+  --> $DIR/dependence_lint.rs:13:12
+   |
+LL |     let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:`
+
+error: unconstrained generic constant
+  --> $DIR/dependence_lint.rs:9:9
+   |
+LL |     [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
new file mode 100644
index 0000000..dcdfd75
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
@@ -0,0 +1,25 @@
+// revisions: full gce
+
+#![cfg_attr(gce, feature(generic_const_exprs))]
+#![allow(incomplete_features)]
+
+use std::mem::size_of;
+
+fn foo<T>() {
+    [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
+    //[gce]~^ ERROR unconstrained
+    //[full]~^^ WARNING cannot use constants
+    //[full]~| WARNING this was previously accepted
+    let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
+    //[full]~^ ERROR generic parameters may not be used
+    //[gce]~^^ ERROR unconstrained generic
+    [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
+    //[gce]~^ ERROR overly complex
+    //[full]~^^ WARNING cannot use constants
+    //[full]~| WARNING this was previously accepted
+    let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
+    //[full]~^ ERROR generic parameters may not be used
+    //[gce]~^^ ERROR overly complex
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/no_dependence.rs b/src/test/ui/const-generics/generic_const_exprs/no_dependence.rs
new file mode 100644
index 0000000..db8dc6e
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/no_dependence.rs
@@ -0,0 +1,13 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn two_args<const N: usize, const M: usize>() -> [u8; M + 2] {
+    [0; M + 2]
+}
+
+fn yay<const N: usize>() -> [u8; 4] {
+     two_args::<N, 2>() // no lint
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
index e1c20e6..16fabd1 100644
--- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
@@ -1,8 +1,8 @@
-error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+error[E0741]: `(dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:9:18
    |
 LL | fn test<const T: &'static dyn A>() {
-   |                  ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq`
+   |                  ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-97278.rs b/src/test/ui/const-generics/issues/issue-97278.rs
new file mode 100644
index 0000000..da0a977
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.rs
@@ -0,0 +1,14 @@
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::sync::Arc;
+
+#[derive(PartialEq, Eq)]
+enum Bar {
+    Bar(Arc<i32>)
+}
+
+fn test<const BAR: Bar>() {}
+//~^ ERROR `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-97278.stderr b/src/test/ui/const-generics/issues/issue-97278.stderr
new file mode 100644
index 0000000..ff13cb5
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-97278.stderr
@@ -0,0 +1,9 @@
+error[E0741]: `Arc<i32>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/issue-97278.rs:11:20
+   |
+LL | fn test<const BAR: Bar>() {}
+   |                    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index 38c38d1..884ae71 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -6,7 +6,7 @@
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
-               ╾─alloc7──╼                                     │ ╾──╼
+               ╾─alloc8──╼                                     │ ╾──╼
            }
 
 error: erroneous constant used
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 6bfa97a..9df1a89 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -6,7 +6,7 @@
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               ╾───────alloc7────────╼                         │ ╾──────╼
+               ╾───────alloc8────────╼                         │ ╾──────╼
            }
 
 error: erroneous constant used
diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs
new file mode 100644
index 0000000..2e78553
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.rs
@@ -0,0 +1,15 @@
+fn borrowck_catch() {
+    let foo = String::new();
+    let _bar = foo;
+    let _baz = [foo; 0]; //~ ERROR use of moved value: `foo` [E0382]
+}
+
+const _: [String; 0] = [String::new(); 0];
+//~^ ERROR destructors cannot be evaluated at compile-time [E0493]
+
+fn must_be_init() {
+    let x: u8;
+    let _ = [x; 0]; //~ ERROR: use of possibly-uninitialized variable: `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
new file mode 100644
index 0000000..cdc5818
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -0,0 +1,29 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/repeat-drop-2.rs:4:17
+   |
+LL |     let foo = String::new();
+   |         --- move occurs because `foo` has type `String`, which does not implement the `Copy` trait
+LL |     let _bar = foo;
+   |                --- value moved here
+LL |     let _baz = [foo; 0];
+   |                 ^^^ value used here after move
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/repeat-drop-2.rs:7:25
+   |
+LL | const _: [String; 0] = [String::new(); 0];
+   |                        -^^^^^^^^^^^^^----
+   |                        ||
+   |                        |constants cannot evaluate destructors
+   |                        value is dropped here
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/repeat-drop-2.rs:12:14
+   |
+LL |     let _ = [x; 0];
+   |              ^ use of possibly-uninitialized `x`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0381, E0382, E0493.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs
new file mode 100644
index 0000000..03e832a
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop.rs
@@ -0,0 +1,120 @@
+// run-pass
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+static mut CHECK: usize = 0;
+
+struct DropChecker(usize);
+
+impl Drop for DropChecker {
+    fn drop(&mut self) {
+        unsafe {
+            if CHECK != self.0 - 1 {
+                panic!("Found {}, should have found {}", CHECK, self.0 - 1);
+            }
+            CHECK = self.0;
+        }
+    }
+}
+
+macro_rules! check_drops {
+    ($l:literal) => {
+        unsafe { assert_eq!(CHECK, $l) }
+    };
+}
+
+struct DropPanic;
+
+impl Drop for DropPanic {
+    fn drop(&mut self) {
+        panic!()
+    }
+}
+
+fn value_zero() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 0] = [foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn value_one() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 1] = [foo; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+const DROP_CHECKER: DropChecker = DropChecker(1);
+
+fn const_zero() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 0] = [DROP_CHECKER; 0];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_one() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 1] = [DROP_CHECKER; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn const_generic_zero<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_generic_one<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Make sure that things are allowed to promote as expected
+
+fn allow_promote() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: &'static [DropChecker; 0] = &[foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Verify that unwinding in the drop causes the right things to drop in the right order
+fn on_unwind() {
+    unsafe { CHECK = 0 };
+    std::panic::catch_unwind(|| {
+        let panic = DropPanic;
+        let _local = DropChecker(2);
+        let _v = (DropChecker(1), [panic; 0]);
+        std::process::abort();
+    })
+    .unwrap_err();
+    check_drops!(2);
+}
+
+fn main() {
+    value_zero();
+    value_one();
+    const_zero();
+    const_one();
+    const_generic_zero::<0>();
+    const_generic_one::<1>();
+    allow_promote();
+    on_unwind();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
new file mode 100644
index 0000000..df81b7d
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
@@ -0,0 +1,13 @@
+#[cfg(target(os = "x"))] //~ ERROR compact `cfg(target(..))` is experimental
+struct Foo(u64, u64);
+
+#[cfg_attr(target(os = "x"), x)] //~ ERROR compact `cfg(target(..))` is experimental
+struct Bar(u64, u64);
+
+#[cfg(not(any(all(target(os = "x")))))] //~ ERROR compact `cfg(target(..))` is experimental
+fn foo() {}
+
+fn main() {
+    cfg!(target(os = "x"));
+    //~^ ERROR compact `cfg(target(..))` is experimental and subject to change
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
new file mode 100644
index 0000000..be6fe23
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
@@ -0,0 +1,39 @@
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:1:7
+   |
+LL | #[cfg(target(os = "x"))]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:4:12
+   |
+LL | #[cfg_attr(target(os = "x"), x)]
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:7:19
+   |
+LL | #[cfg(not(any(all(target(os = "x")))))]
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:11:10
+   |
+LL |     cfg!(target(os = "x"));
+   |          ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index cf9f89d..06e1bd8 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,3 +1,17 @@
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:17
+   |
+LL |     mod inner { #![macro_escape] }
+   |                 ^^^^^^^^^^^^^^^^
+   |
+   = help: try an outer attribute: `#[macro_use]`
+
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:1
+   |
+LL | #[macro_escape]
+   | ^^^^^^^^^^^^^^^
+
 warning: unknown lint: `x5400`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9
    |
@@ -172,20 +186,6 @@
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
-warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:17
-   |
-LL |     mod inner { #![macro_escape] }
-   |                 ^^^^^^^^^^^^^^^^
-   |
-   = help: try an outer attribute: `#[macro_use]`
-
-warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:1
-   |
-LL | #[macro_escape]
-   | ^^^^^^^^^^^^^^^
-
 warning: use of deprecated attribute `crate_id`: no longer used.
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:1
    |
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index 98fd135..3ffd35e 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -1,8 +1,9 @@
 // run-pass
 // needs-unwind
 // ignore-wasm32-bare compiled with panic=abort by default
-// revisions: mir thir
+// revisions: mir thir strict
 // [thir]compile-flags: -Zthir-unsafeck
+// [strict]compile-flags: -Zstrict-init-checks
 // ignore-tidy-linelength
 
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
@@ -54,6 +55,8 @@
     Right(num::NonZeroI64),
 }
 
+struct ZeroSized;
+
 fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
     let err = panic::catch_unwind(op).err();
     assert_eq!(
@@ -228,11 +231,40 @@
         let _val = mem::zeroed::<[!; 0]>();
         let _val = mem::uninitialized::<MaybeUninit<bool>>();
         let _val = mem::uninitialized::<[!; 0]>();
+        let _val = mem::uninitialized::<()>();
+        let _val = mem::uninitialized::<ZeroSized>();
 
-        // These are UB because they have not been officially blessed, but we await the resolution
-        // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
-        // anything about that.
-        let _val = mem::uninitialized::<i32>();
-        let _val = mem::uninitialized::<*const ()>();
+        if cfg!(strict) {
+            test_panic_msg(
+                || mem::uninitialized::<i32>(),
+                "attempted to leave type `i32` uninitialized, which is invalid"
+            );
+
+            test_panic_msg(
+                || mem::uninitialized::<*const ()>(),
+                "attempted to leave type `*const ()` uninitialized, which is invalid"
+            );
+
+            test_panic_msg(
+                || mem::uninitialized::<[i32; 1]>(),
+                "attempted to leave type `[i32; 1]` uninitialized, which is invalid"
+            );
+
+            test_panic_msg(
+                || mem::zeroed::<NonNull<()>>(),
+                "attempted to zero-initialize type `core::ptr::non_null::NonNull<()>`, which is invalid"
+            );
+
+            test_panic_msg(
+                || mem::zeroed::<[NonNull<()>; 1]>(),
+                "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid"
+            );
+        } else {
+            // These are UB because they have not been officially blessed, but we await the resolution
+            // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
+            // anything about that.
+            let _val = mem::uninitialized::<i32>();
+            let _val = mem::uninitialized::<*const ()>();
+        }
     }
 }
diff --git a/src/test/ui/json-multiple.nll.stderr b/src/test/ui/json-multiple.nll.stderr
deleted file mode 100644
index c2cb8bc..0000000
--- a/src/test/ui/json-multiple.nll.stderr
+++ /dev/null
@@ -1 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/json-multiple.nll/libjson_multiple.rlib","emit":"link"}
diff --git a/src/test/ui/json-multiple.rs b/src/test/ui/json-multiple.rs
index fb12633..4c37e20 100644
--- a/src/test/ui/json-multiple.rs
+++ b/src/test/ui/json-multiple.rs
@@ -1,5 +1,6 @@
 // build-pass
 // ignore-pass (different metadata emitted in different modes)
 // compile-flags: --json=diagnostic-short --json artifacts --error-format=json
+// ignore-compare-mode-nll
 
 #![crate_type = "lib"]
diff --git a/src/test/ui/json-options.nll.stderr b/src/test/ui/json-options.nll.stderr
deleted file mode 100644
index f19a9cd..0000000
--- a/src/test/ui/json-options.nll.stderr
+++ /dev/null
@@ -1 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/json-options.nll/libjson_options.rlib","emit":"link"}
diff --git a/src/test/ui/json-options.rs b/src/test/ui/json-options.rs
index 8b6ba13..fea07cc 100644
--- a/src/test/ui/json-options.rs
+++ b/src/test/ui/json-options.rs
@@ -1,5 +1,6 @@
 // build-pass
 // ignore-pass (different metadata emitted in different modes)
 // compile-flags: --json=diagnostic-short,artifacts --error-format=json
+// ignore-compare-mode-nll
 
 #![crate_type = "lib"]
diff --git a/src/test/ui/lint/issue-97094.interleaved.stderr b/src/test/ui/lint/issue-97094.interleaved.stderr
new file mode 100644
index 0000000..a258165
--- /dev/null
+++ b/src/test/ui/lint/issue-97094.interleaved.stderr
@@ -0,0 +1,53 @@
+error: unknown lint: `nonex_lint_top_level`
+  --> $DIR/issue-97094.rs:14:26
+   |
+LL | #![cfg_attr(all(), allow(nonex_lint_top_level))]
+   |                          ^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-97094.rs:10:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]`
+
+error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+  --> $DIR/issue-97094.rs:16:26
+   |
+LL | #![cfg_attr(all(), allow(bare_trait_object))]
+   |                          ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects`
+   |
+   = note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]`
+
+error: unknown lint: `nonex_lint_mod`
+  --> $DIR/issue-97094.rs:19:25
+   |
+LL | #[cfg_attr(all(), allow(nonex_lint_mod))]
+   |                         ^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_mod_inner`
+  --> $DIR/issue-97094.rs:22:30
+   |
+LL |     #![cfg_attr(all(), allow(nonex_lint_mod_inner))]
+   |                              ^^^^^^^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_fn`
+  --> $DIR/issue-97094.rs:26:25
+   |
+LL | #[cfg_attr(all(), allow(nonex_lint_fn))]
+   |                         ^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_in_macro`
+  --> $DIR/issue-97094.rs:37:29
+   |
+LL |     #[cfg_attr(all(), allow(nonex_lint_in_macro))]
+   |                             ^^^^^^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_fn`
+  --> $DIR/issue-97094.rs:56:13
+   |
+LL |     #[allow(nonex_lint_fn)]
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/lint/issue-97094.nointerleaved.stderr b/src/test/ui/lint/issue-97094.nointerleaved.stderr
new file mode 100644
index 0000000..a258165
--- /dev/null
+++ b/src/test/ui/lint/issue-97094.nointerleaved.stderr
@@ -0,0 +1,53 @@
+error: unknown lint: `nonex_lint_top_level`
+  --> $DIR/issue-97094.rs:14:26
+   |
+LL | #![cfg_attr(all(), allow(nonex_lint_top_level))]
+   |                          ^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-97094.rs:10:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]`
+
+error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
+  --> $DIR/issue-97094.rs:16:26
+   |
+LL | #![cfg_attr(all(), allow(bare_trait_object))]
+   |                          ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects`
+   |
+   = note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]`
+
+error: unknown lint: `nonex_lint_mod`
+  --> $DIR/issue-97094.rs:19:25
+   |
+LL | #[cfg_attr(all(), allow(nonex_lint_mod))]
+   |                         ^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_mod_inner`
+  --> $DIR/issue-97094.rs:22:30
+   |
+LL |     #![cfg_attr(all(), allow(nonex_lint_mod_inner))]
+   |                              ^^^^^^^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_fn`
+  --> $DIR/issue-97094.rs:26:25
+   |
+LL | #[cfg_attr(all(), allow(nonex_lint_fn))]
+   |                         ^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_in_macro`
+  --> $DIR/issue-97094.rs:37:29
+   |
+LL |     #[cfg_attr(all(), allow(nonex_lint_in_macro))]
+   |                             ^^^^^^^^^^^^^^^^^^^
+
+error: unknown lint: `nonex_lint_fn`
+  --> $DIR/issue-97094.rs:56:13
+   |
+LL |     #[allow(nonex_lint_fn)]
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/lint/issue-97094.rs b/src/test/ui/lint/issue-97094.rs
new file mode 100644
index 0000000..aeaead1
--- /dev/null
+++ b/src/test/ui/lint/issue-97094.rs
@@ -0,0 +1,59 @@
+// revisions: interleaved nointerleaved
+// [nointerleaved]compile-flags: -Z no-interleave-lints
+
+// This test has two revisions because the logic change
+// needed to make this test pass had to be adjusted
+// for no-interleave-lints. Should the debug option
+// be removed one day, please don't remove this
+// test entirely, just remove the revision from it.
+
+#![deny(warnings)]
+
+// Ensure that unknown lints inside cfg-attr's are linted for
+
+#![cfg_attr(all(), allow(nonex_lint_top_level))]
+//~^ ERROR unknown lint
+#![cfg_attr(all(), allow(bare_trait_object))]
+//~^ ERROR has been renamed
+
+#[cfg_attr(all(), allow(nonex_lint_mod))]
+//~^ ERROR unknown lint
+mod baz {
+    #![cfg_attr(all(), allow(nonex_lint_mod_inner))]
+    //~^ ERROR unknown lint
+}
+
+#[cfg_attr(all(), allow(nonex_lint_fn))]
+//~^ ERROR unknown lint
+pub fn main() {}
+
+macro_rules! bar {
+    ($($t:tt)*) => {
+        $($t)*
+    };
+}
+
+bar!(
+    #[cfg_attr(all(), allow(nonex_lint_in_macro))]
+    //~^ ERROR unknown lint
+    pub fn _bar() {}
+);
+
+// No warning for non-applying cfg
+#[cfg_attr(any(), allow(nonex_lint_fn))]
+pub fn _foo() {}
+
+// Allowing unknown lints works if inside cfg_attr
+#[cfg_attr(all(), allow(unknown_lints))]
+mod bar_allowed {
+    #[allow(nonex_lint_fn)]
+    fn _foo() {}
+}
+
+// ... but not if the cfg_attr doesn't evaluate
+#[cfg_attr(any(), allow(unknown_lints))]
+mod bar_not_allowed {
+    #[allow(nonex_lint_fn)]
+    //~^ ERROR unknown lint
+    fn _foo() {}
+}
diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr
index f65ca08..5521af1 100644
--- a/src/test/ui/lint/reasons-erroneous.stderr
+++ b/src/test/ui/lint/reasons-erroneous.stderr
@@ -58,14 +58,6 @@
 LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
-warning: unknown lint: `reason`
-  --> $DIR/reasons-erroneous.rs:50:39
-   |
-LL | #![warn(missing_copy_implementations, reason)]
-   |                                       ^^^^^^
-   |
-   = note: `#[warn(unknown_lints)]` on by default
-
 error[E0452]: malformed lint attribute input
   --> $DIR/reasons-erroneous.rs:3:58
    |
@@ -126,6 +118,14 @@
 LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
+warning: unknown lint: `reason`
+  --> $DIR/reasons-erroneous.rs:50:39
+   |
+LL | #![warn(missing_copy_implementations, reason)]
+   |                                       ^^^^^^
+   |
+   = note: `#[warn(unknown_lints)]` on by default
+
 error: aborting due to 20 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/src/test/ui/native-library-link-flags/modifiers-override-3.rs b/src/test/ui/native-library-link-flags/modifiers-override-3.rs
new file mode 100644
index 0000000..b28c53c
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/modifiers-override-3.rs
@@ -0,0 +1,7 @@
+// Regression test for issue #97299, one command line library with modifiers
+// overrides another command line library with modifiers.
+
+// compile-flags:-lstatic:+whole-archive=foo -lstatic:+whole-archive=foo
+// error-pattern: overriding linking modifiers from command line is not supported
+
+fn main() {}
diff --git a/src/test/ui/native-library-link-flags/modifiers-override-3.stderr b/src/test/ui/native-library-link-flags/modifiers-override-3.stderr
new file mode 100644
index 0000000..365e561
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/modifiers-override-3.stderr
@@ -0,0 +1,4 @@
+error: overriding linking modifiers from command line is not supported
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/else-no-if.rs b/src/test/ui/parser/else-no-if.rs
new file mode 100644
index 0000000..f0b40ec
--- /dev/null
+++ b/src/test/ui/parser/else-no-if.rs
@@ -0,0 +1,32 @@
+fn foo() {
+    if true {
+    } else false {
+    //~^ ERROR expected `{`, found keyword `false`
+    }
+}
+
+fn foo2() {
+    if true {
+    } else falsy() {
+    //~^ ERROR expected `{`, found `falsy`
+    }
+}
+
+fn foo3() {
+    if true {
+    } else falsy();
+    //~^ ERROR expected `{`, found `falsy`
+}
+
+fn foo4() {
+    if true {
+    } else loop{}
+    //~^ ERROR expected `{`, found keyword `loop`
+    {}
+}
+
+fn falsy() -> bool {
+    false
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/else-no-if.stderr b/src/test/ui/parser/else-no-if.stderr
new file mode 100644
index 0000000..b9c1a75
--- /dev/null
+++ b/src/test/ui/parser/else-no-if.stderr
@@ -0,0 +1,50 @@
+error: expected `{`, found keyword `false`
+  --> $DIR/else-no-if.rs:3:12
+   |
+LL |     } else false {
+   |       ---- ^^^^^
+   |       |
+   |       expected an `if` or a block after this `else`
+   |
+help: add an `if` if this is the condition of a chained `else if` statement
+   |
+LL |     } else if false {
+   |            ++
+
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:10:12
+   |
+LL |     } else falsy() {
+   |       ---- ^^^^^
+   |       |
+   |       expected an `if` or a block after this `else`
+   |
+help: add an `if` if this is the condition of a chained `else if` statement
+   |
+LL |     } else if falsy() {
+   |            ++
+
+error: expected `{`, found `falsy`
+  --> $DIR/else-no-if.rs:17:12
+   |
+LL |     } else falsy();
+   |            ^^^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     } else { falsy() };
+   |            +         +
+
+error: expected `{`, found keyword `loop`
+  --> $DIR/else-no-if.rs:23:12
+   |
+LL |     } else loop{}
+   |            ^^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     } else { loop{} }
+   |            +        +
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs
new file mode 100644
index 0000000..ecd3f58
--- /dev/null
+++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs
@@ -0,0 +1,46 @@
+struct A {
+    config: String,
+}
+
+impl A {
+    fn new(cofig: String) -> Self {
+        Self { config } //~ Error cannot find value `config` in this scope
+    }
+
+    fn do_something(cofig: String) {
+        println!("{config}"); //~ Error cannot find value `config` in this scope
+    }
+
+    fn self_is_available(self, cofig: String) {
+        println!("{config}"); //~ Error cannot find value `config` in this scope
+    }
+}
+
+trait B {
+    const BAR: u32 = 3;
+    type Baz;
+    fn bar(&self);
+    fn baz(&self) {}
+    fn bah() {}
+}
+
+impl B for Box<isize> {
+    type Baz = String;
+    fn bar(&self) {
+        // let baz = 3;
+        baz();
+        //~^ ERROR cannot find function `baz`
+        bah;
+        //~^ ERROR cannot find value `bah`
+        BAR;
+        //~^ ERROR cannot find value `BAR` in this scope
+        let foo: Baz = "".to_string();
+        //~^ ERROR cannot find type `Baz` in this scope
+    }
+}
+
+fn ba() {}
+const BARR: u32 = 3;
+type Bar = String;
+
+fn main() {}
diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr
new file mode 100644
index 0000000..0b0a37f
--- /dev/null
+++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr
@@ -0,0 +1,109 @@
+error[E0425]: cannot find value `config` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16
+   |
+LL |         Self { config }
+   |                ^^^^^^
+   |                |
+   |                a field by this name exists in `Self`
+   |                help: a local variable with a similar name exists: `cofig`
+
+error[E0425]: cannot find value `config` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20
+   |
+LL |         println!("{config}");
+   |                    ^^^^^^
+   |                    |
+   |                    a field by this name exists in `Self`
+   |                    help: a local variable with a similar name exists: `cofig`
+
+error[E0425]: cannot find value `config` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20
+   |
+LL |         println!("{config}");
+   |                    ^^^^^^
+   |
+help: you might have meant to use the available field
+   |
+LL |         println!("{self.config}");
+   |                    ~~~~~~~~~~~
+help: a local variable with a similar name exists
+   |
+LL |         println!("{cofig}");
+   |                    ~~~~~
+
+error[E0425]: cannot find function `baz` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:31:9
+   |
+LL |         baz();
+   |         ^^^
+...
+LL | fn ba() {}
+   | ------- similarly named function `ba` defined here
+   |
+help: you might have meant to call the method
+   |
+LL |         self.baz();
+   |         ~~~~~~~~
+help: a function with a similar name exists
+   |
+LL |         ba();
+   |         ~~
+
+error[E0425]: cannot find value `bah` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:33:9
+   |
+LL |         bah;
+   |         ^^^
+...
+LL | fn ba() {}
+   | ------- similarly named function `ba` defined here
+   |
+help: you might have meant to call the associated function
+   |
+LL |         Self::bah;
+   |         ~~~~~~~~~
+help: a function with a similar name exists
+   |
+LL |         ba;
+   |         ~~
+
+error[E0425]: cannot find value `BAR` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:35:9
+   |
+LL |         BAR;
+   |         ^^^
+...
+LL | const BARR: u32 = 3;
+   | -------------------- similarly named constant `BARR` defined here
+   |
+help: you might have meant to use the associated `const`
+   |
+LL |         Self::BAR;
+   |         ~~~~~~~~~
+help: a constant with a similar name exists
+   |
+LL |         BARR;
+   |         ~~~~
+
+error[E0412]: cannot find type `Baz` in this scope
+  --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:37:18
+   |
+LL |         let foo: Baz = "".to_string();
+   |                  ^^^
+...
+LL | type Bar = String;
+   | ------------------ similarly named type alias `Bar` defined here
+   |
+help: you might have meant to use the associated type
+   |
+LL |         let foo: Self::Baz = "".to_string();
+   |                  ~~~~~~~~~
+help: a type alias with a similar name exists
+   |
+LL |         let foo: Bar = "".to_string();
+   |                  ~~~
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/rmeta/emit-artifact-notifications.nll.stderr b/src/test/ui/rmeta/emit-artifact-notifications.nll.stderr
deleted file mode 100644
index ed62f30..0000000
--- a/src/test/ui/rmeta/emit-artifact-notifications.nll.stderr
+++ /dev/null
@@ -1 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta","emit":"metadata"}
diff --git a/src/test/ui/rmeta/emit-artifact-notifications.rs b/src/test/ui/rmeta/emit-artifact-notifications.rs
index 984a7fa..be38fb4 100644
--- a/src/test/ui/rmeta/emit-artifact-notifications.rs
+++ b/src/test/ui/rmeta/emit-artifact-notifications.rs
@@ -2,6 +2,7 @@
 // build-pass
 // ignore-pass
 // ^-- needed because `--pass check` does not emit the output needed.
+// ignore-compare-mode-nll
 
 // A very basic test for the emission of artifact notifications in JSON output.
 
diff --git a/src/test/ui/save-analysis/emit-notifications.nll.stderr b/src/test/ui/save-analysis/emit-notifications.nll.stderr
deleted file mode 100644
index 60734ce..0000000
--- a/src/test/ui/save-analysis/emit-notifications.nll.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.nll/save-analysis/libemit_notifications.json","emit":"save-analysis"}
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.nll/libemit_notifications.rlib","emit":"link"}
diff --git a/src/test/ui/save-analysis/emit-notifications.rs b/src/test/ui/save-analysis/emit-notifications.rs
index 9179944..8a69669 100644
--- a/src/test/ui/save-analysis/emit-notifications.rs
+++ b/src/test/ui/save-analysis/emit-notifications.rs
@@ -3,5 +3,6 @@
 // compile-flags: --crate-type rlib --error-format=json
 // ignore-pass
 // ^-- needed because otherwise, the .stderr file changes with --pass check
+// ignore-compare-mode-nll
 
 pub fn foo() {}
diff --git a/src/test/ui/traits/issue-82830.rs b/src/test/ui/traits/issue-82830.rs
new file mode 100644
index 0000000..c8289b2
--- /dev/null
+++ b/src/test/ui/traits/issue-82830.rs
@@ -0,0 +1,16 @@
+trait A<Y, N> {
+    type B;
+}
+
+type MaybeBox<T> = <T as A<T, Box<T>>>::B;
+struct P {
+    t: MaybeBox<P>, //~ ERROR: overflow evaluating the requirement `P: Sized`
+}
+
+impl<Y, N> A<Y, N> for P {
+    type B = N;
+}
+
+fn main() {
+    let t: MaybeBox<P>;
+}
diff --git a/src/test/ui/traits/issue-82830.stderr b/src/test/ui/traits/issue-82830.stderr
new file mode 100644
index 0000000..f863143
--- /dev/null
+++ b/src/test/ui/traits/issue-82830.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `P: Sized`
+  --> $DIR/issue-82830.rs:7:8
+   |
+LL |     t: MaybeBox<P>,
+   |        ^^^^^^^^^^^
+   |
+note: required because of the requirements on the impl of `A<P, Box<P>>` for `P`
+  --> $DIR/issue-82830.rs:10:12
+   |
+LL | impl<Y, N> A<Y, N> for P {
+   |            ^^^^^^^     ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.rs b/src/test/ui/type/type-check/unknown_type_for_closure.rs
index 0dbf824..0089d86 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.rs
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.rs
@@ -1,3 +1,17 @@
-fn main() {
-    let x = |_| {    }; //~ ERROR type annotations needed
+fn infer_in_arg() {
+    let x = |b: Vec<_>| {}; //~ ERROR E0282
 }
+
+fn empty_pattern() {
+    let x = |_| {}; //~ ERROR type annotations needed
+}
+
+fn infer_ty() {
+    let x = |k: _| {}; //~ ERROR type annotations needed
+}
+
+fn ambig_return() {
+    let x = || -> Vec<_> { Vec::new() }; //~ ERROR type annotations needed for the closure `fn() -> Vec<_>`
+}
+
+fn main() {}
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.stderr b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
index 5971f56..c3accad 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.stderr
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
@@ -1,9 +1,32 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/unknown_type_for_closure.rs:2:14
    |
-LL |     let x = |_| {    };
+LL |     let x = |b: Vec<_>| {};
    |              ^ consider giving this closure parameter a type
 
-error: aborting due to previous error
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:6:14
+   |
+LL |     let x = |_| {};
+   |              ^ consider giving this closure parameter a type
+
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:10:14
+   |
+LL |     let x = |k: _| {};
+   |              ^ consider giving this closure parameter a type
+
+error[E0282]: type annotations needed for the closure `fn() -> Vec<_>`
+  --> $DIR/unknown_type_for_closure.rs:14:28
+   |
+LL |     let x = || -> Vec<_> { Vec::new() };
+   |                            ^^^^^^^^ cannot infer type for type parameter `T`
+   |
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |     let x = || -> Vec<_> { Vec::new() };
+   |                   ~~~~~~
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0282`.
diff --git a/src/tools/cargo b/src/tools/cargo
index a4c1cd0..39ad103 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit a4c1cd0eb6b18082a7e693f5a665548fe1534be4
+Subproject commit 39ad1039d9e3e1746177bf5d134af4c164f95528
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index af56ec1..fff7da8 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -12,12 +12,12 @@
 
 use super::UNNECESSARY_CAST;
 
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    cast_expr: &Expr<'_>,
-    cast_from: Ty<'_>,
-    cast_to: Ty<'_>,
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'tcx>,
+    cast_expr: &Expr<'tcx>,
+    cast_from: Ty<'tcx>,
+    cast_to: Ty<'tcx>,
 ) -> bool {
     // skip non-primitive type cast
     if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index ea4c020..8288f7a 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -446,7 +446,7 @@
 
 // Checks whether the type for a deref call actually changed the type, not just the mutability of
 // the reference.
-fn deref_method_same_type(result_ty: Ty<'_>, arg_ty: Ty<'_>) -> bool {
+fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
     match (result_ty.kind(), arg_ty.kind()) {
         (ty::Ref(_, result_ty, _), ty::Ref(_, arg_ty, _)) => result_ty == arg_ty,
 
@@ -541,8 +541,8 @@
 /// Adjustments are sometimes made in the parent block rather than the expression itself.
 fn find_adjustments<'tcx>(
     tcx: TyCtxt<'tcx>,
-    typeck: &'tcx TypeckResults<'_>,
-    expr: &'tcx Expr<'_>,
+    typeck: &'tcx TypeckResults<'tcx>,
+    expr: &'tcx Expr<'tcx>,
 ) -> &'tcx [Adjustment<'tcx>] {
     let map = tcx.hir();
     let mut iter = map.parent_iter(expr.hir_id);
@@ -581,7 +581,7 @@
 }
 
 #[expect(clippy::needless_pass_by_value)]
-fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData) {
+fn report<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, state: State, data: StateData) {
     match state {
         State::DerefMethod {
             ty_changed_count,
@@ -656,7 +656,7 @@
 }
 
 impl Dereferencing {
-    fn check_local_usage(&mut self, cx: &LateContext<'_>, e: &Expr<'_>, local: HirId) {
+    fn check_local_usage<'tcx>(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) {
         if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
             if let Some(pat) = outer_pat {
                 // Check for auto-deref
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index dabbb83..246f5aa 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -259,8 +259,8 @@
     }
 }
 
-impl LenOutput<'_> {
-    fn matches_is_empty_output(self, ty: Ty<'_>) -> bool {
+impl<'tcx> LenOutput<'tcx> {
+    fn matches_is_empty_output(self, ty: Ty<'tcx>) -> bool {
         match (self, ty.kind()) {
             (_, &ty::Bool) => true,
             (Self::Option(id), &ty::Adt(adt, subs)) if id == adt.did() => subs.type_at(0).is_bool(),
@@ -292,7 +292,7 @@
 }
 
 /// Checks if the given signature matches the expectations for `is_empty`
-fn check_is_empty_sig(sig: FnSig<'_>, self_kind: ImplicitSelfKind, len_output: LenOutput<'_>) -> bool {
+fn check_is_empty_sig<'tcx>(sig: FnSig<'tcx>, self_kind: ImplicitSelfKind, len_output: LenOutput<'tcx>) -> bool {
     match &**sig.inputs_and_output {
         [arg, res] if len_output.matches_is_empty_output(*res) => {
             matches!(
@@ -306,11 +306,11 @@
 }
 
 /// Checks if the given type has an `is_empty` method with the appropriate signature.
-fn check_for_is_empty(
-    cx: &LateContext<'_>,
+fn check_for_is_empty<'tcx>(
+    cx: &LateContext<'tcx>,
     span: Span,
     self_kind: ImplicitSelfKind,
-    output: LenOutput<'_>,
+    output: LenOutput<'tcx>,
     impl_ty: DefId,
     item_name: Symbol,
     item_kind: &str,
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 35fc452..3bf48e1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -2843,7 +2843,7 @@
 
 impl SelfKind {
     fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
-        fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool {
+        fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
             if ty == parent_ty {
                 true
             } else if ty.is_box() {
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 86460c1..548f7b2 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -395,9 +395,9 @@
 
 fn check_fn_args<'cx, 'tcx: 'cx>(
     cx: &'cx LateContext<'tcx>,
-    tys: &'tcx [Ty<'_>],
-    hir_tys: &'tcx [hir::Ty<'_>],
-    params: &'tcx [Param<'_>],
+    tys: &'tcx [Ty<'tcx>],
+    hir_tys: &'tcx [hir::Ty<'tcx>],
+    params: &'tcx [Param<'tcx>],
 ) -> impl Iterator<Item = PtrArg<'tcx>> + 'cx {
     tys.iter()
         .zip(hir_tys.iter())
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 0004b8a..ab16fe4 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -292,7 +292,7 @@
         if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
         if !is_copy(cx, inner_ty);
         then {
-            Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)?.as_local()?))
+            Some((def_id, *local, inner_ty, destination.as_local()?))
         } else {
             None
         }
@@ -584,7 +584,7 @@
     fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
         if let mir::TerminatorKind::Call {
             args,
-            destination: Some((mir::Place { local: dest, .. }, _)),
+            destination: mir::Place { local: dest, .. },
             ..
         } = &terminator.kind
         {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index be62773..20b348f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -358,7 +358,7 @@
     }
 }
 
-fn same_except_params(subs1: SubstsRef<'_>, subs2: SubstsRef<'_>) -> bool {
+fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> bool {
     // TODO: check const parameters as well. Currently this will consider `Array<5>` the same as
     // `Array<6>`
     for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index a6d7042..78d8f1e 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -301,6 +301,7 @@
             args,
             from_hir_call: _,
             destination: _,
+            target: _,
             cleanup: _,
             fn_span: _,
         } => {
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 07d3d28..75d27d3 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -42,7 +42,7 @@
 }
 
 /// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
-pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
+pub fn contains_ty<'tcx>(ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool {
     ty.walk().any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => other_ty == inner_ty,
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
@@ -51,7 +51,7 @@
 
 /// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
 /// constructor.
-pub fn contains_adt_constructor(ty: Ty<'_>, adt: AdtDef<'_>) -> bool {
+pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
     ty.walk().any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a59a058..64b6df3 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3112,7 +3112,7 @@
         let expected_fixed = self.load_expected_output(UI_FIXED);
 
         let modes_to_prune = vec![CompareMode::Nll];
-        self.prune_duplicate_outputs(&modes_to_prune);
+        self.check_and_prune_duplicate_outputs(&proc_res, &[], &modes_to_prune);
 
         let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit);
         let rustfix_input = json::rustfix_diagnostics_only(&proc_res.stderr);
@@ -3730,28 +3730,54 @@
         if self.config.bless { 0 } else { 1 }
     }
 
-    fn prune_duplicate_output(&self, mode: CompareMode, kind: &str, canon_content: &str) {
-        let examined_path = expected_output_path(&self.testpaths, self.revision, &Some(mode), kind);
+    fn check_and_prune_duplicate_outputs(
+        &self,
+        proc_res: &ProcRes,
+        modes: &[CompareMode],
+        require_same_modes: &[CompareMode],
+    ) {
+        for kind in UI_EXTENSIONS {
+            let canon_comparison_path =
+                expected_output_path(&self.testpaths, self.revision, &None, kind);
 
-        let examined_content =
-            self.load_expected_output_from_path(&examined_path).unwrap_or_else(|_| String::new());
+            let canon = match self.load_expected_output_from_path(&canon_comparison_path) {
+                Ok(canon) => canon,
+                _ => continue,
+            };
+            let bless = self.config.bless;
+            let check_and_prune_duplicate_outputs = |mode: &CompareMode, require_same: bool| {
+                let examined_path =
+                    expected_output_path(&self.testpaths, self.revision, &Some(mode.clone()), kind);
 
-        if canon_content == examined_content {
-            self.delete_file(&examined_path);
-        }
-    }
+                // If there is no output, there is nothing to do
+                let examined_content = match self.load_expected_output_from_path(&examined_path) {
+                    Ok(content) => content,
+                    _ => return,
+                };
 
-    fn prune_duplicate_outputs(&self, modes: &[CompareMode]) {
-        if self.config.bless {
-            for kind in UI_EXTENSIONS {
-                let canon_comparison_path =
-                    expected_output_path(&self.testpaths, self.revision, &None, kind);
+                let is_duplicate = canon == examined_content;
 
-                if let Ok(canon) = self.load_expected_output_from_path(&canon_comparison_path) {
-                    for mode in modes {
-                        self.prune_duplicate_output(mode.clone(), kind, &canon);
+                match (bless, require_same, is_duplicate) {
+                    // If we're blessing and the output is the same, then delete the file.
+                    (true, _, true) => {
+                        self.delete_file(&examined_path);
                     }
+                    // If we want them to be the same, but they are different, then error.
+                    // We do this wether we bless or not
+                    (_, true, false) => {
+                        self.fatal_proc_rec(
+                            &format!("`{}` should not have different output from base test!", kind),
+                            proc_res,
+                        );
+                    }
+                    _ => {}
                 }
+            };
+            for mode in modes {
+                check_and_prune_duplicate_outputs(mode, false);
+            }
+            for mode in require_same_modes {
+                check_and_prune_duplicate_outputs(mode, true);
             }
         }
     }
diff --git a/src/tools/lld-wrapper/Cargo.toml b/src/tools/lld-wrapper/Cargo.toml
index 66a586f..bf5138b 100644
--- a/src/tools/lld-wrapper/Cargo.toml
+++ b/src/tools/lld-wrapper/Cargo.toml
@@ -3,9 +3,3 @@
 version = "0.1.0"
 edition = "2021"
 license = "MIT OR Apache-2.0"
-
-[dependencies]
-
-[features]
-ld = []
-ld64 = []
\ No newline at end of file
diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs
index 8d19a05..90bd24a 100644
--- a/src/tools/lld-wrapper/src/main.rs
+++ b/src/tools/lld-wrapper/src/main.rs
@@ -1,5 +1,4 @@
-//! Script to invoke the bundled rust-lld with the correct flavor. The flavor is selected by
-//! feature.
+//! Script to invoke the bundled rust-lld with the correct flavor.
 //!
 //! lld supports multiple command line interfaces. If `-flavor <flavor>` are passed as the first
 //! two arguments the `<flavor>` command line interface is used to process the remaining arguments.
@@ -8,59 +7,33 @@
 //! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to
 //! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
 //! and since Windows does not support symbolic links for files this wrapper is used in place of a
-//! symbolic link. It execs `../rust-lld -flavor ld` if the feature `ld` is enabled and
-//! `../rust-lld -flavor ld64` if `ld64` is enabled. On Windows it spawns a `..\rust-lld.exe`
+//! symbolic link. It execs `../rust-lld -flavor <flavor>` by propagating the flavor argument
+//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe`
 //! child process.
 
-#[cfg(not(any(feature = "ld", feature = "ld64")))]
-compile_error!("One of the features ld and ld64 must be enabled.");
-
-#[cfg(all(feature = "ld", feature = "ld64"))]
-compile_error!("Only one of the feature ld or ld64 can be enabled.");
-
-#[cfg(feature = "ld")]
-const FLAVOR: &str = "ld";
-
-#[cfg(feature = "ld64")]
-const FLAVOR: &str = "ld64";
-
-use std::env;
 use std::fmt::Display;
 use std::path::{Path, PathBuf};
-use std::process;
+use std::{env, process};
 
-trait ResultExt<T, E> {
+trait UnwrapOrExitWith<T> {
     fn unwrap_or_exit_with(self, context: &str) -> T;
 }
 
-impl<T, E> ResultExt<T, E> for Result<T, E>
-where
-    E: Display,
-{
+impl<T> UnwrapOrExitWith<T> for Option<T> {
     fn unwrap_or_exit_with(self, context: &str) -> T {
-        match self {
-            Ok(t) => t,
-            Err(e) => {
-                eprintln!("lld-wrapper: {}: {}", context, e);
-                process::exit(1);
-            }
-        }
+        self.unwrap_or_else(|| {
+            eprintln!("lld-wrapper: {}", context);
+            process::exit(1);
+        })
     }
 }
 
-trait OptionExt<T> {
-    fn unwrap_or_exit_with(self, context: &str) -> T;
-}
-
-impl<T> OptionExt<T> for Option<T> {
+impl<T, E: Display> UnwrapOrExitWith<T> for Result<T, E> {
     fn unwrap_or_exit_with(self, context: &str) -> T {
-        match self {
-            Some(t) => t,
-            None => {
-                eprintln!("lld-wrapper: {}", context);
-                process::exit(1);
-            }
-        }
+        self.unwrap_or_else(|err| {
+            eprintln!("lld-wrapper: {}: {}", context, err);
+            process::exit(1);
+        })
     }
 }
 
@@ -81,14 +54,28 @@
 }
 
 /// Returns the command for invoking rust-lld with the correct flavor.
+/// LLD only accepts the flavor argument at the first two arguments, so move it there.
 ///
 /// Exits on error.
 fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
     let rust_lld_path = get_rust_lld_path(current_exe_path);
     let mut command = process::Command::new(rust_lld_path);
+
+    let mut flavor = None;
+    let args = env::args_os()
+        .skip(1)
+        .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) {
+            Some(suffix) => {
+                flavor = Some(suffix.to_string());
+                false
+            }
+            None => true,
+        })
+        .collect::<Vec<_>>();
+
     command.arg("-flavor");
-    command.arg(FLAVOR);
-    command.args(env::args_os().skip(1));
+    command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor=<flavor> is not passed"));
+    command.args(args);
     command
 }
 
@@ -101,20 +88,14 @@
 
 #[cfg(not(unix))]
 fn exec_lld(mut command: process::Command) {
-    // Windows has no exec(), spawn a child process and wait for it
+    // Windows has no exec(), spawn a child process and wait for it.
     let exit_status = command.status().unwrap_or_exit_with("error running rust-lld child process");
-    if !exit_status.success() {
-        match exit_status.code() {
-            Some(code) => {
-                // return the original lld exit code
-                process::exit(code)
-            }
-            None => {
-                eprintln!("lld-wrapper: rust-lld child process exited with error: {}", exit_status,);
-                process::exit(1);
-            }
-        }
-    }
+    let code = exit_status
+        .code()
+        .ok_or(exit_status)
+        .unwrap_or_exit_with("rust-lld child process exited with error");
+    // Return the original lld exit code.
+    process::exit(code);
 }
 
 fn main() {
diff --git a/src/tools/miri b/src/tools/miri
index b96610b..22c97b3 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit b96610b3de5bc9fd346d90700ba881aca8d503f0
+Subproject commit 22c97b33e470d0b7c085e98417bef8b362d43d4e