about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_abi/src/layout.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs117
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs28
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs16
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs11
-rw-r--r--compiler/rustc_hir/src/hir.rs120
-rw-r--r--compiler/rustc_hir/src/intravisit.rs12
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs99
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs68
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs3
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs24
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs26
-rw-r--r--compiler/rustc_lint/src/builtin.rs160
-rw-r--r--compiler/rustc_lint/src/internal.rs6
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs12
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs7
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs11
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs45
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs1
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs2
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs2
-rw-r--r--compiler/rustc_span/src/def_id.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs28
-rw-r--r--library/core/src/mem/mod.rs61
-rw-r--r--library/std/src/sys/common/alloc.rs12
-rw-r--r--src/bootstrap/bin/rustc.rs8
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/test.rs36
-rw-r--r--src/librustdoc/clean/mod.rs41
-rw-r--r--src/librustdoc/doctest.rs16
-rw-r--r--src/librustdoc/html/static/js/main.js20
-rw-r--r--src/librustdoc/html/static/js/settings.js2
-rw-r--r--src/test/run-make/coverage-reports/Makefile2
-rw-r--r--src/test/rustdoc-gui/notable-trait.goml25
-rw-r--r--src/test/rustdoc-gui/pocket-menu.goml21
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml52
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.rs4
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.stderr8
-rw-r--r--src/test/ui/async-await/generator-desc.stderr8
-rw-r--r--src/test/ui/async-await/issue-67252-unnamed-future.stderr2
-rw-r--r--src/test/ui/async-await/issue-86507.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr22
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr2
-rw-r--r--src/test/ui/constructor-lifetime-args.stderr8
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr13
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr13
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.rs9
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr5
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr5
-rw-r--r--src/test/ui/generator/clone-impl-async.rs27
-rw-r--r--src/test/ui/generator/clone-impl-async.stderr48
-rw-r--r--src/test/ui/generic-associated-types/elided-in-expr-position.stderr4
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-81862.stderr2
-rw-r--r--src/test/ui/generic-associated-types/missing_lifetime_args.stderr4
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr2
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr12
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.rs2
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.stderr2
-rw-r--r--src/test/ui/layout/valid_range_oob.rs15
-rw-r--r--src/test/ui/layout/valid_range_oob.stderr6
-rw-r--r--src/test/ui/lint/invalid_value.stderr69
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.stderr8
-rw-r--r--src/test/ui/pattern/non-structural-match-types.stderr2
-rw-r--r--src/test/ui/stats/hir-stats.stderr8
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr2
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs66
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr162
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.stderr24
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs16
-rw-r--r--src/tools/jsondoclint/src/json_find.rs5
-rw-r--r--src/tools/jsondoclint/src/json_find/tests.rs27
-rw-r--r--src/tools/jsondoclint/src/main.rs4
-rw-r--r--triagebot.toml9
101 files changed, 1192 insertions, 704 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 39ea7a85be6..11e7b80f85e 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -382,28 +382,26 @@ pub trait LayoutCalculator {
             let (start, end) = scalar_valid_range;
             match st.abi {
                 Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
-                    // the asserts ensure that we are not using the
-                    // `#[rustc_layout_scalar_valid_range(n)]`
-                    // attribute to widen the range of anything as that would probably
-                    // result in UB somewhere
-                    // FIXME(eddyb) the asserts are probably not needed,
-                    // as larger validity ranges would result in missed
+                    // Enlarging validity ranges would result in missed
                     // optimizations, *not* wrongly assuming the inner
-                    // value is valid. e.g. unions enlarge validity ranges,
+                    // value is valid. e.g. unions already enlarge validity ranges,
                     // because the values may be uninitialized.
+                    //
+                    // Because of that we only check that the start and end
+                    // of the range is representable with this scalar type.
+
+                    let max_value = scalar.size(dl).unsigned_int_max();
                     if let Bound::Included(start) = start {
                         // FIXME(eddyb) this might be incorrect - it doesn't
                         // account for wrap-around (end < start) ranges.
-                        let valid_range = scalar.valid_range_mut();
-                        assert!(valid_range.start <= start);
-                        valid_range.start = start;
+                        assert!(start <= max_value, "{start} > {max_value}");
+                        scalar.valid_range_mut().start = start;
                     }
                     if let Bound::Included(end) = end {
                         // FIXME(eddyb) this might be incorrect - it doesn't
                         // account for wrap-around (end < start) ranges.
-                        let valid_range = scalar.valid_range_mut();
-                        assert!(valid_range.end >= end);
-                        valid_range.end = end;
+                        assert!(end <= max_value, "{end} > {max_value}");
+                        scalar.valid_range_mut().end = end;
                     }
 
                     // Update `largest_niche` if we have introduced a larger niche.
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 23a38a092d9..c14c591d387 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -605,6 +605,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             output,
             c_variadic: false,
             implicit_self: hir::ImplicitSelfKind::None,
+            lifetime_elision_allowed: false,
         });
 
         // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
@@ -917,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
         // Lower outside new scope to preserve `is_in_loop_condition`.
-        let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
+        let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
 
         let c = self.arena.alloc(hir::Closure {
             def_id: self.local_def_id(closure_id),
@@ -1027,7 +1028,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // have to conserve the state of being inside a loop condition for the
         // closure argument types.
         let fn_decl =
-            self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
+            self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
 
         let c = self.arena.alloc(hir::Closure {
             def_id: self.local_def_id(closure_id),
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 695a698e022..9def8536c82 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -303,7 +303,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
-        self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
+        self.insert(lifetime.ident.span, lifetime.hir_id, Node::Lifetime(lifetime));
     }
 
     fn visit_variant(&mut self, v: &'hir Variant<'hir>) {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index a1941b5d8d3..2b47e908912 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let mut itctx = ImplTraitContext::Universal;
                     let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
                         let ret_id = asyncness.opt_return_id();
-                        this.lower_fn_decl(&decl, Some(id), *fn_sig_span, FnDeclKind::Fn, ret_id)
+                        this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
                     });
                     let sig = hir::FnSig {
                         decl,
@@ -659,7 +659,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                 // Disallow `impl Trait` in foreign items.
                                 this.lower_fn_decl(
                                     fdec,
-                                    None,
+                                    i.id,
                                     sig.span,
                                     FnDeclKind::ExternFn,
                                     None,
@@ -1247,7 +1247,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let header = self.lower_fn_header(sig.header);
         let mut itctx = ImplTraitContext::Universal;
         let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
-            this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
+            this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
         });
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
@@ -1479,10 +1479,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }))
             }
             GenericParamKind::Lifetime => {
-                let ident_span = self.lower_span(ident.span);
                 let ident = self.lower_ident(ident);
                 let lt_id = self.next_node_id();
-                let lifetime = self.new_named_lifetime(id, lt_id, ident_span, ident);
+                let lifetime = self.new_named_lifetime(id, lt_id, ident);
                 Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
                     lifetime,
                     span,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 4ec943f33e2..a123a58a8fb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -327,7 +327,14 @@ enum FnDeclKind {
 }
 
 impl FnDeclKind {
-    fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+    fn param_impl_trait_allowed(&self) -> bool {
+        match self {
+            FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
+            _ => false,
+        }
+    }
+
+    fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
         match self {
             FnDeclKind::Fn | FnDeclKind::Inherent => true,
             FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
@@ -1255,7 +1262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     } else {
                         self.next_node_id()
                     };
-                    let span = self.tcx.sess.source_map().start_point(t.span);
+                    let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
                     Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
                 });
                 let lifetime = self.lower_lifetime(&region);
@@ -1267,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     generic_params,
                     unsafety: self.lower_unsafety(f.unsafety),
                     abi: self.lower_extern(f.ext),
-                    decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
+                    decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
                     param_names: self.lower_fn_params_to_names(&f.decl),
                 }))
             }
@@ -1546,15 +1553,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let lifetimes =
             self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
                 let id = self.next_node_id();
-                let span = lifetime.ident.span;
-
-                let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
-                    Ident::with_dummy_span(kw::UnderscoreLifetime)
-                } else {
-                    lifetime.ident
-                };
-
-                let l = self.new_named_lifetime(lifetime.id, id, span, ident);
+                let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
                 hir::GenericArg::Lifetime(l)
             }));
         debug!(?lifetimes);
@@ -1679,7 +1678,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_fn_decl(
         &mut self,
         decl: &FnDecl,
-        fn_node_id: Option<NodeId>,
+        fn_node_id: NodeId,
         fn_span: Span,
         kind: FnDeclKind,
         make_ret_async: Option<(NodeId, Span)>,
@@ -1694,23 +1693,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             inputs = &inputs[..inputs.len() - 1];
         }
         let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
-            if fn_node_id.is_some() {
-                self.lower_ty_direct(&param.ty, &ImplTraitContext::Universal)
+            let itctx = if kind.param_impl_trait_allowed() {
+                ImplTraitContext::Universal
             } else {
-                self.lower_ty_direct(
-                    &param.ty,
-                    &ImplTraitContext::Disallowed(match kind {
-                        FnDeclKind::Fn | FnDeclKind::Inherent => {
-                            unreachable!("fn should allow in-band lifetimes")
-                        }
-                        FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
-                        FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
-                        FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
-                        FnDeclKind::Trait => ImplTraitPosition::TraitParam,
-                        FnDeclKind::Impl => ImplTraitPosition::ImplParam,
-                    }),
-                )
-            }
+                ImplTraitContext::Disallowed(match kind {
+                    FnDeclKind::Fn | FnDeclKind::Inherent => {
+                        unreachable!("fn should allow APIT")
+                    }
+                    FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
+                    FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
+                    FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
+                    FnDeclKind::Trait => ImplTraitPosition::TraitParam,
+                    FnDeclKind::Impl => ImplTraitPosition::ImplParam,
+                })
+            };
+            self.lower_ty_direct(&param.ty, &itctx)
         }));
 
         let output = if let Some((ret_id, span)) = make_ret_async {
@@ -1733,22 +1730,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
             self.lower_async_fn_ret_ty(
                 &decl.output,
-                fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+                fn_node_id,
                 ret_id,
                 matches!(kind, FnDeclKind::Trait),
             )
         } else {
             match &decl.output {
                 FnRetTy::Ty(ty) => {
-                    let mut context = match fn_node_id {
-                        Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
-                            let fn_def_id = self.local_def_id(fn_node_id);
-                            ImplTraitContext::ReturnPositionOpaqueTy {
-                                origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
-                                in_trait: matches!(kind, FnDeclKind::Trait),
-                            }
+                    let mut context = if kind.return_impl_trait_allowed(self.tcx) {
+                        let fn_def_id = self.local_def_id(fn_node_id);
+                        ImplTraitContext::ReturnPositionOpaqueTy {
+                            origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+                            in_trait: matches!(kind, FnDeclKind::Trait),
                         }
-                        _ => ImplTraitContext::Disallowed(match kind {
+                    } else {
+                        ImplTraitContext::Disallowed(match kind {
                             FnDeclKind::Fn | FnDeclKind::Inherent => {
                                 unreachable!("fn should allow in-band lifetimes")
                             }
@@ -1757,7 +1753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
                             FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
                             FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
-                        }),
+                        })
                     };
                     hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
                 }
@@ -1769,6 +1765,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             inputs,
             output,
             c_variadic,
+            lifetime_elision_allowed: self.resolver.lifetime_elision_allowed.contains(&fn_node_id),
             implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
                 let is_mutable_pat = matches!(
                     arg.pat.kind,
@@ -2010,18 +2007,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
             |(_, lifetime, res)| {
                 let id = self.next_node_id();
-                let span = lifetime.ident.span;
-
-                let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
-                    Ident::with_dummy_span(kw::UnderscoreLifetime)
-                } else {
-                    lifetime.ident
-                };
-
                 let res = res.unwrap_or(
                     self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
                 );
-                hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
+                hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
             },
         ));
 
@@ -2091,43 +2080,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
-        let span = self.lower_span(l.ident.span);
         let ident = self.lower_ident(l.ident);
-        self.new_named_lifetime(l.id, l.id, span, ident)
+        self.new_named_lifetime(l.id, l.id, ident)
     }
 
     #[instrument(level = "debug", skip(self))]
     fn new_named_lifetime_with_res(
         &mut self,
         id: NodeId,
-        span: Span,
         ident: Ident,
         res: LifetimeRes,
     ) -> &'hir hir::Lifetime {
-        let name = match res {
+        let res = match res {
             LifetimeRes::Param { param, .. } => {
-                let p_name = ParamName::Plain(ident);
                 let param = self.get_remapped_def_id(param);
-
-                hir::LifetimeName::Param(param, p_name)
+                hir::LifetimeName::Param(param)
             }
             LifetimeRes::Fresh { param, .. } => {
-                debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
                 let param = self.local_def_id(param);
-
-                hir::LifetimeName::Param(param, ParamName::Fresh)
+                hir::LifetimeName::Param(param)
             }
             LifetimeRes::Infer => hir::LifetimeName::Infer,
             LifetimeRes::Static => hir::LifetimeName::Static,
             LifetimeRes::Error => hir::LifetimeName::Error,
-            res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),
+            res => panic!(
+                "Unexpected lifetime resolution {:?} for {:?} at {:?}",
+                res, ident, ident.span
+            ),
         };
 
-        debug!(?name);
+        debug!(?res);
         self.arena.alloc(hir::Lifetime {
             hir_id: self.lower_node_id(id),
-            span: self.lower_span(span),
-            name,
+            ident: self.lower_ident(ident),
+            res,
         })
     }
 
@@ -2136,11 +2122,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         id: NodeId,
         new_id: NodeId,
-        span: Span,
         ident: Ident,
     ) -> &'hir hir::Lifetime {
         let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
-        self.new_named_lifetime_with_res(new_id, span, ident, res)
+        self.new_named_lifetime_with_res(new_id, ident, res)
     }
 
     fn lower_generic_params_mut<'s>(
@@ -2552,8 +2537,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
         let r = hir::Lifetime {
             hir_id: self.next_id(),
-            span: self.lower_span(span),
-            name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
+            ident: Ident::new(kw::Empty, self.lower_span(span)),
+            res: hir::LifetimeName::ImplicitObjectLifetimeDefault,
         };
         debug!("elided_dyn_bound: r={:?}", r);
         self.arena.alloc(r)
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 27b44c0b6a2..dc85b5e95ea 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -309,7 +309,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let id = NodeId::from_u32(i);
                 let l = self.lower_lifetime(&Lifetime {
                     id,
-                    ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span),
+                    ident: Ident::new(kw::Empty, elided_lifetime_span),
                 });
                 GenericArg::Lifetime(l)
             }),
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 919117651e2..5ec9c5f5c1b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2670,7 +2670,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind {
                                 // With access to the lifetime, we can get
                                 // the span of it.
-                                arguments.push((*argument, lifetime.span));
+                                arguments.push((*argument, lifetime.ident.span));
                             } else {
                                 bug!("ty type is a ref but hir type is not");
                             }
@@ -2689,7 +2689,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let mut return_span = fn_decl.output.span();
                 if let hir::FnRetTy::Return(ty) = &fn_decl.output {
                     if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
-                        return_span = lifetime.span;
+                        return_span = lifetime.ident.span;
                     }
                 }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 5122f9808ed..0cf66e41001 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1211,7 +1211,7 @@ fn get_mut_span_in_struct_field<'tcx>(
         && let hir::Node::Field(field) = node
         && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind
     {
-        return Some(lt.span.between(ty.span));
+        return Some(lt.ident.span.between(ty.span));
     }
 
     None
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 0adaabd0dbf..39173e70acf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -576,30 +576,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let args = last_segment.args.as_ref()?;
         let lifetime =
             self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
-        match lifetime.name {
-            hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error)
-            | hir::LifetimeName::Error
-            | hir::LifetimeName::Static => {
-                let lifetime_span = lifetime.span;
-                Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
-            }
-
-            hir::LifetimeName::Param(_, hir::ParamName::Fresh)
-            | hir::LifetimeName::ImplicitObjectLifetimeDefault
-            | hir::LifetimeName::Infer => {
-                // In this case, the user left off the lifetime; so
-                // they wrote something like:
-                //
-                // ```
-                // x: Foo<T>
-                // ```
-                //
-                // where the fully elaborated form is `Foo<'_, '1,
-                // T>`. We don't consider this a match; instead we let
-                // the "fully elaborated" type fallback above handle
-                // it.
-                None
-            }
+        if lifetime.is_anonymous() {
+            None
+        } else {
+            Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
         }
     }
 
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 89661918d05..fd01fcf1fc8 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -13,17 +13,17 @@
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
-#[cfg(all(any(target_arch = "x86",
+#[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
               target_arch = "powerpc",
-              target_arch = "powerpc64")))]
+              target_arch = "powerpc64"))]
 const MIN_ALIGN: usize = 8;
-#[cfg(all(any(target_arch = "x86_64",
+#[cfg(any(target_arch = "x86_64",
               target_arch = "aarch64",
               target_arch = "mips64",
               target_arch = "s390x",
-              target_arch = "sparc64")))]
+              target_arch = "sparc64"))]
 const MIN_ALIGN: usize = 16;
 
 pub struct System;
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index cd7a472c0f0..0e85c7d11bc 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -785,18 +785,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 }
             }
             Abi::ScalarPair(a_layout, b_layout) => {
-                // There is no `rustc_layout_scalar_valid_range_start` for pairs, so
-                // we would validate these things as we descend into the fields,
-                // but that can miss bugs in layout computation. Layout computation
-                // is subtle due to enums having ScalarPair layout, where one field
-                // is the discriminant.
-                if cfg!(debug_assertions)
-                    && !a_layout.is_uninit_valid()
-                    && !b_layout.is_uninit_valid()
-                {
-                    // We can only proceed if *both* scalars need to be initialized.
-                    // FIXME: find a way to also check ScalarPair when one side can be uninit but
-                    // the other must be init.
+                // We can only proceed if *both* scalars need to be initialized.
+                // FIXME: find a way to also check ScalarPair when one side can be uninit but
+                // the other must be init.
+                if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
                     let (a, b) =
                         self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 27fb95dcd40..b19d270e610 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -376,7 +376,7 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
         ccx: &ConstCx<'_, 'tcx>,
         span: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
+        let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
         if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
             ccx.tcx.sess.create_feature_err(
                 UnallowedOpInConstContext { span, msg },
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 860dee58980..bf700d31224 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -81,6 +81,7 @@ struct TypeChecker<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    #[track_caller]
     fn fail(&self, location: Location, msg: impl AsRef<str>) {
         let span = self.body.source_info(location).span;
         // We use `delay_span_bug` as we might see broken MIR when other errors have already
@@ -226,12 +227,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 let check_equal = |this: &Self, location, f_ty| {
                     if !this.mir_assign_valid_types(ty, f_ty) {
                         this.fail(
-                        location,
-                        format!(
-                            "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
-                            parent, f, ty, f_ty
+                            location,
+                            format!(
+                                "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
+                                parent, f, ty, f_ty
+                            )
                         )
-                    )
                     }
                 };
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 042e65fc4df..81aedcce877 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -29,15 +29,16 @@ use std::fmt;
 #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
 pub struct Lifetime {
     pub hir_id: HirId,
-    pub span: Span,
 
     /// Either "`'a`", referring to a named lifetime definition,
-    /// or "``" (i.e., `kw::Empty`), for elision placeholders.
+    /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`),
+    /// or "``" (i.e., `kw::Empty`) when appearing in path.
     ///
-    /// HIR lowering inserts these placeholders in type paths that
-    /// refer to type definitions needing lifetime parameters,
-    /// `&T` and `&mut T`, and trait objects without `... + 'a`.
-    pub name: LifetimeName,
+    /// See `Lifetime::suggestion_position` for practical use.
+    pub ident: Ident,
+
+    /// Semantics of this lifetime.
+    pub res: LifetimeName,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
@@ -88,7 +89,7 @@ impl ParamName {
 #[derive(HashStable_Generic)]
 pub enum LifetimeName {
     /// User-given names or fresh (synthetic) names.
-    Param(LocalDefId, ParamName),
+    Param(LocalDefId),
 
     /// Implicit lifetime in a context like `dyn Foo`. This is
     /// distinguished from implicit lifetimes elsewhere because the
@@ -116,25 +117,6 @@ pub enum LifetimeName {
 }
 
 impl LifetimeName {
-    pub fn ident(&self) -> Ident {
-        match *self {
-            LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(),
-            LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime),
-            LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
-            LifetimeName::Param(_, param_name) => param_name.ident(),
-        }
-    }
-
-    pub fn is_anonymous(&self) -> bool {
-        match *self {
-            LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Infer
-            | LifetimeName::Param(_, ParamName::Fresh)
-            | LifetimeName::Error => true,
-            LifetimeName::Static | LifetimeName::Param(..) => false,
-        }
-    }
-
     pub fn is_elided(&self) -> bool {
         match self {
             LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
@@ -146,34 +128,54 @@ impl LifetimeName {
             LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
         }
     }
-
-    fn is_static(&self) -> bool {
-        self == &LifetimeName::Static
-    }
-
-    pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
-        match *self {
-            LifetimeName::Param(def_id, param_name) => {
-                LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0())
-            }
-            lifetime_name => lifetime_name,
-        }
-    }
 }
 
 impl fmt::Display for Lifetime {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.name.ident().fmt(f)
+        if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
     }
 }
 
+pub enum LifetimeSuggestionPosition {
+    /// The user wrote `'a` or `'_`.
+    Normal,
+    /// The user wrote `&type` or `&mut type`.
+    Ampersand,
+    /// The user wrote `Path` and omitted the `<'_>`.
+    ElidedPath,
+    /// The user wrote `Path<T>`, and omitted the `'_,`.
+    ElidedPathArgument,
+    /// The user wrote `dyn Trait` and omitted the `+ '_`.
+    ObjectDefault,
+}
+
 impl Lifetime {
     pub fn is_elided(&self) -> bool {
-        self.name.is_elided()
+        self.res.is_elided()
+    }
+
+    pub fn is_anonymous(&self) -> bool {
+        self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
+    }
+
+    pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
+        if self.ident.name == kw::Empty {
+            if self.ident.span.is_empty() {
+                (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span)
+            } else {
+                (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi())
+            }
+        } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault {
+            (LifetimeSuggestionPosition::ObjectDefault, self.ident.span)
+        } else if self.ident.span.is_empty() {
+            (LifetimeSuggestionPosition::Ampersand, self.ident.span)
+        } else {
+            (LifetimeSuggestionPosition::Normal, self.ident.span)
+        }
     }
 
     pub fn is_static(&self) -> bool {
-        self.name.is_static()
+        self.res == LifetimeName::Static
     }
 }
 
@@ -267,7 +269,7 @@ pub enum GenericArg<'hir> {
 impl GenericArg<'_> {
     pub fn span(&self) -> Span {
         match self {
-            GenericArg::Lifetime(l) => l.span,
+            GenericArg::Lifetime(l) => l.ident.span,
             GenericArg::Type(t) => t.span,
             GenericArg::Const(c) => c.span,
             GenericArg::Infer(i) => i.span,
@@ -284,7 +286,7 @@ impl GenericArg<'_> {
     }
 
     pub fn is_synthetic(&self) -> bool {
-        matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty())
+        matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty())
     }
 
     pub fn descr(&self) -> &'static str {
@@ -446,7 +448,7 @@ impl GenericBound<'_> {
         match self {
             GenericBound::Trait(t, ..) => t.span,
             GenericBound::LangItemTrait(_, span, ..) => *span,
-            GenericBound::Outlives(l) => l.span,
+            GenericBound::Outlives(l) => l.ident.span,
         }
     }
 }
@@ -560,6 +562,19 @@ impl<'hir> Generics<'hir> {
     }
 
     /// If there are generic parameters, return where to introduce a new one.
+    pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
+        if let Some(first) = self.params.first()
+            && self.span.contains(first.span)
+        {
+            // `fn foo<A>(t: impl Trait)`
+            //         ^ suggest `'a, ` here
+            Some(first.span.shrink_to_lo())
+        } else {
+            None
+        }
+    }
+
+    /// If there are generic parameters, return where to introduce a new one.
     pub fn span_for_param_suggestion(&self) -> Option<Span> {
         if self.params.iter().any(|p| self.span.contains(p.span)) {
             // `fn foo<A>(t: impl Trait)`
@@ -765,10 +780,7 @@ pub struct WhereRegionPredicate<'hir> {
 impl<'hir> WhereRegionPredicate<'hir> {
     /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate.
     pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
-        match self.lifetime.name {
-            LifetimeName::Param(id, _) => id == param_def_id,
-            _ => false,
-        }
+        self.lifetime.res == LifetimeName::Param(param_def_id)
     }
 }
 
@@ -1514,9 +1526,9 @@ pub enum AsyncGeneratorKind {
 impl fmt::Display for AsyncGeneratorKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match self {
-            AsyncGeneratorKind::Block => "`async` block",
-            AsyncGeneratorKind::Closure => "`async` closure body",
-            AsyncGeneratorKind::Fn => "`async fn` body",
+            AsyncGeneratorKind::Block => "async block",
+            AsyncGeneratorKind::Closure => "async closure body",
+            AsyncGeneratorKind::Fn => "async fn body",
         })
     }
 }
@@ -2688,6 +2700,8 @@ pub struct FnDecl<'hir> {
     pub c_variadic: bool,
     /// Does the function have an implicit self?
     pub implicit_self: ImplicitSelfKind,
+    /// Is lifetime elision allowed.
+    pub lifetime_elision_allowed: bool,
 }
 
 /// Represents what type of implicit self a function has, if any.
@@ -3453,7 +3467,7 @@ impl<'hir> Node<'hir> {
             | Node::Variant(Variant { ident, .. })
             | Node::Item(Item { ident, .. })
             | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
-            Node::Lifetime(lt) => Some(lt.name.ident()),
+            Node::Lifetime(lt) => Some(lt.ident),
             Node::GenericParam(p) => Some(p.name.ident()),
             Node::TypeBinding(b) => Some(b.ident),
             Node::Param(..)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 48db93fde9d..957f8c1058e 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -1109,17 +1109,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v Ge
 
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
     visitor.visit_id(lifetime.hir_id);
-    match lifetime.name {
-        LifetimeName::Param(_, ParamName::Plain(ident)) => {
-            visitor.visit_ident(ident);
-        }
-        LifetimeName::Param(_, ParamName::Fresh)
-        | LifetimeName::Param(_, ParamName::Error)
-        | LifetimeName::Static
-        | LifetimeName::Error
-        | LifetimeName::ImplicitObjectLifetimeDefault
-        | LifetimeName::Infer => {}
-    }
+    visitor.visit_ident(lifetime.ident);
 }
 
 pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 1c55cd8fee8..98d967cc0b8 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(associated_type_defaults)]
 #![feature(closure_track_caller)]
 #![feature(const_btree_len)]
+#![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 4d858bc7f61..5f06db4038f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -241,14 +241,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
 
             None => {
-                self.re_infer(def, lifetime.span).unwrap_or_else(|| {
+                self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
                     debug!(?lifetime, "unelided lifetime in signature");
 
                     // This indicates an illegal lifetime
                     // elision. `resolve_lifetime` should have
                     // reported an error in this case -- but if
                     // not, let's error out.
-                    tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
+                    tcx.sess.delay_span_bug(lifetime.ident.span, "unelided lifetime in signature");
 
                     // Supply some dummy value. We don't have an
                     // `re_error`, annoyingly, so use `'static`.
@@ -961,9 +961,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 hir::GenericBound::Outlives(lifetime) => {
                     let region = self.ast_region_to_region(lifetime, None);
-                    bounds
-                        .region_bounds
-                        .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
+                    bounds.region_bounds.push((
+                        ty::Binder::bind_with_vars(region, bound_vars),
+                        lifetime.ident.span,
+                    ));
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index b369a1eb109..639f81f20bf 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -398,7 +398,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
                 Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
                 Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
                 Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
-                    self.has_late_bound_regions = Some(lt.span);
+                    self.has_late_bound_regions = Some(lt.ident.span);
                 }
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index da1c04f3f7b..c11eed7ad9e 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -595,7 +595,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         this.visit_poly_trait_ref(bound);
                     }
                 });
-                match lifetime.name {
+                match lifetime.res {
                     LifetimeName::ImplicitObjectLifetimeDefault => {
                         // If the user does not write *anything*, we
                         // use the object lifetime defaulting
@@ -686,7 +686,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     if !parent_id.is_owner() {
                         struct_span_err!(
                             self.tcx.sess,
-                            lifetime.span,
+                            lifetime.ident.span,
                             E0657,
                             "`impl Trait` can only capture lifetimes bound at the fn or impl level"
                         )
@@ -698,7 +698,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     }) = self.tcx.hir().get(parent_id)
                     {
                         let mut err = self.tcx.sess.struct_span_err(
-                            lifetime.span,
+                            lifetime.ident.span,
                             "higher kinded lifetime bounds on nested opaque types are not supported yet",
                         );
                         err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
@@ -802,9 +802,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
-        match lifetime_ref.name {
+        match lifetime_ref.res {
             hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
-            hir::LifetimeName::Param(param_def_id, _) => {
+            hir::LifetimeName::Param(param_def_id) => {
                 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
             }
             // If we've already reported an error, just ignore `lifetime_ref`.
@@ -912,27 +912,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         this.visit_lifetime(lifetime);
                         walk_list!(this, visit_param_bound, bounds);
 
-                        if lifetime.name != hir::LifetimeName::Static {
+                        if lifetime.res != hir::LifetimeName::Static {
                             for bound in bounds {
                                 let hir::GenericBound::Outlives(ref lt) = bound else {
                                     continue;
                                 };
-                                if lt.name != hir::LifetimeName::Static {
+                                if lt.res != hir::LifetimeName::Static {
                                     continue;
                                 }
                                 this.insert_lifetime(lt, Region::Static);
                                 this.tcx
                                     .sess
                                     .struct_span_warn(
-                                        lifetime.span,
+                                        lifetime.ident.span,
                                         &format!(
                                             "unnecessary lifetime parameter `{}`",
-                                            lifetime.name.ident(),
+                                            lifetime.ident,
                                         ),
                                     )
                                     .help(&format!(
                                         "you can use the `'static` lifetime directly, in place of `{}`",
-                                        lifetime.name.ident(),
+                                        lifetime.ident,
                                     ))
                                     .emit();
                             }
@@ -1043,7 +1043,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
 
                 for bound in bound.bounds {
                     if let hir::GenericBound::Outlives(ref lifetime) = *bound {
-                        set.insert(lifetime.name.normalize_to_macros_2_0());
+                        set.insert(lifetime.res);
                     }
                 }
             }
@@ -1051,7 +1051,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
             match set {
                 Set1::Empty => ObjectLifetimeDefault::Empty,
                 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
-                Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
+                Set1::One(hir::LifetimeName::Param(param_def_id)) => {
                     ObjectLifetimeDefault::Param(param_def_id.to_def_id())
                 }
                 _ => ObjectLifetimeDefault::Ambiguous,
@@ -1195,42 +1195,50 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
                     // regular fns.
                     if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
-                        && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
+                        && let hir::LifetimeName::Param(_) = lifetime_ref.res
+                        && lifetime_ref.is_anonymous()
                         && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
                     {
                         let mut diag =  rustc_session::parse::feature_err(
                             &self.tcx.sess.parse_sess,
                             sym::anonymous_lifetime_in_impl_trait,
-                            lifetime_ref.span,
+                            lifetime_ref.ident.span,
                             "anonymous lifetimes in `impl Trait` are unstable",
                         );
 
-                        match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) {
-                            Some(generics) => {
-
-                                let new_param_sugg_tuple;
-
-                                new_param_sugg_tuple = match generics.span_for_param_suggestion() {
-                                    Some(_) => {
-                                        Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()))
-                                    },
-                                    None => Some((generics.span, "<'a>".to_owned()))
-                                };
-
-                                let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())];
-
-                                if let Some(new_tuple) =  new_param_sugg_tuple{
-                                    multi_sugg_vec.push(new_tuple);
-                                }
-
-                                diag.span_label(lifetime_ref.span, "expected named lifetime parameter");
-                                diag.multipart_suggestion("consider introducing a named lifetime parameter",
-                                multi_sugg_vec,
-                                rustc_errors::Applicability::MaybeIncorrect);
-
-                            },
-                            None => { }
+                        if let Some(generics) =
+                            self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
+                        {
+                            let new_param_sugg = if let Some(span) =
+                                generics.span_for_lifetime_suggestion()
+                            {
+                                (span, "'a, ".to_owned())
+                            } else {
+                                (generics.span, "<'a>".to_owned())
+                            };
+
+                            let lifetime_sugg = match lifetime_ref.suggestion_position() {
+                                (hir::LifetimeSuggestionPosition::Normal, span) => (span, "'a".to_owned()),
+                                (hir::LifetimeSuggestionPosition::Ampersand, span) => (span, "'a ".to_owned()),
+                                (hir::LifetimeSuggestionPosition::ElidedPath, span) => (span, "<'a>".to_owned()),
+                                (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => (span, "'a, ".to_owned()),
+                                (hir::LifetimeSuggestionPosition::ObjectDefault, span) => (span, "+ 'a".to_owned()),
+                            };
+                            let suggestions = vec![
+                                lifetime_sugg,
+                                new_param_sugg,
+                            ];
+
+                            diag.span_label(
+                                lifetime_ref.ident.span,
+                                "expected named lifetime parameter",
+                            );
+                            diag.multipart_suggestion(
+                                "consider introducing a named lifetime parameter",
+                                suggestions,
+                                rustc_errors::Applicability::MaybeIncorrect,
+                            );
                         }
 
                         diag.emit();
@@ -1287,7 +1295,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
                 } => {
                     let mut err = self.tcx.sess.struct_span_err(
-                        lifetime_ref.span,
+                        lifetime_ref.ident.span,
                         "`impl Trait` can only mention lifetimes bound at the fn or impl level",
                     );
                     err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
@@ -1307,7 +1315,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
 
         self.tcx.sess.delay_span_bug(
-            lifetime_ref.span,
+            lifetime_ref.ident.span,
             &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
         );
     }
@@ -1625,10 +1633,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
-        debug!(
-            node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
-            span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
-        );
+        debug!(span = ?lifetime_ref.ident.span);
         self.map.defs.insert(lifetime_ref.hir_id, def);
     }
 
@@ -1839,7 +1844,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
         }
 
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
+            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
                 self.regions.insert(def_id);
             }
         }
@@ -1852,7 +1857,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
 
     impl<'v> Visitor<'v> for AllCollector {
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
-            if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
+            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
                 self.regions.insert(def_id);
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 9417a2620d1..45e241f4e09 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -229,7 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 predicates.extend(region_pred.bounds.iter().map(|bound| {
                     let (r2, span) = match bound {
                         hir::GenericBound::Outlives(lt) => {
-                            (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span)
+                            (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span)
                         }
                         _ => bug!(),
                     };
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 9c77387c238..4451db19f5c 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -296,25 +296,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
     ) -> String {
         debug!(?path_hir_id);
 
+        // If there was already a lifetime among the arguments, just replicate that one.
+        if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg {
+            hir::GenericArg::Lifetime(lt) => Some(lt),
+            _ => None,
+        }) {
+            return std::iter::repeat(lt.to_string())
+                .take(num_params_to_take)
+                .collect::<Vec<_>>()
+                .join(", ");
+        }
+
         let mut ret = Vec::new();
+        let mut ty_id = None;
         for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
             debug!(?id);
-            let params = if let Some(generics) = node.generics() {
-                generics.params
-            } else if let hir::Node::Ty(ty) = node
-                && let hir::TyKind::BareFn(bare_fn) = ty.kind
-            {
-                bare_fn.generic_params
-            } else {
-                &[]
-            };
-            ret.extend(params.iter().filter_map(|p| {
-                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
-                    = p.kind
-                else { return None };
-                let hir::ParamName::Plain(name) = p.name else { return None };
-                Some(name.to_string())
-            }));
+            if let hir::Node::Ty(_) = node {
+                ty_id = Some(id);
+            }
+
+            // Suggest `'_` when in function parameter or elided function return.
+            if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id {
+                let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id);
+                let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
+
+                if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) {
+                    return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", ");
+                }
+            }
+
             // Suggest `'static` when in const/static item-like.
             if let hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
@@ -334,11 +344,29 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             })
             | hir::Node::AnonConst(..) = node
             {
-                ret.extend(
-                    std::iter::repeat("'static".to_owned())
-                        .take(num_params_to_take.saturating_sub(ret.len())),
-                );
+                return std::iter::repeat("'static".to_owned())
+                    .take(num_params_to_take.saturating_sub(ret.len()))
+                    .collect::<Vec<_>>()
+                    .join(", ");
             }
+
+            let params = if let Some(generics) = node.generics() {
+                generics.params
+            } else if let hir::Node::Ty(ty) = node
+                && let hir::TyKind::BareFn(bare_fn) = ty.kind
+            {
+                bare_fn.generic_params
+            } else {
+                &[]
+            };
+            ret.extend(params.iter().filter_map(|p| {
+                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
+                    = p.kind
+                else { return None };
+                let hir::ParamName::Plain(name) = p.name else { return None };
+                Some(name.to_string())
+            }));
+
             if ret.len() >= num_params_to_take {
                 return ret[..num_params_to_take].join(", ");
             }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 99a7f52efdb..95729822677 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2159,7 +2159,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
-        self.print_ident(lifetime.name.ident())
+        self.print_ident(lifetime.ident)
     }
 
     pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 50722c42a6c..4e044d39d50 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -118,7 +118,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                 } else {
                     let note = format!(
                         "the type is part of the {} because of this {}",
-                        self.kind, yield_data.source
+                        self.kind.descr(),
+                        yield_data.source
                     );
 
                     self.fcx
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index ec4eeb8caa2..74c4c65cc17 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -375,7 +375,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
                 return false;
             };
 
-            if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() {
+            if !lifetime_sub.is_anonymous() || !lifetime_sup.is_anonymous() {
                 return false;
             };
 
@@ -407,20 +407,20 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
             let suggestion_param_name =
                 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
 
-            debug!(?lifetime_sup.span);
-            debug!(?lifetime_sub.span);
-            let make_suggestion = |span: rustc_span::Span| {
-                if span.is_empty() {
-                    (span, format!("{}, ", suggestion_param_name))
-                } else if let Ok("&") = self.tcx.sess.source_map().span_to_snippet(span).as_deref()
-                {
-                    (span.shrink_to_hi(), format!("{} ", suggestion_param_name))
+            debug!(?lifetime_sup.ident.span);
+            debug!(?lifetime_sub.ident.span);
+            let make_suggestion = |ident: Ident| {
+                let sugg = if ident.name == kw::Empty {
+                    format!("{}, ", suggestion_param_name)
+                } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
+                    format!("{} ", suggestion_param_name)
                 } else {
-                    (span, suggestion_param_name.clone())
-                }
+                    suggestion_param_name.clone()
+                };
+                (ident.span, sugg)
             };
             let mut suggestions =
-                vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)];
+                vec![make_suggestion(lifetime_sub.ident), make_suggestion(lifetime_sup.ident)];
 
             if introduce_new {
                 let new_param_suggestion = if let Some(first) =
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index b4efe8da125..09f9aa3c842 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -314,10 +314,10 @@ pub fn suggest_new_region_bound(
                     .iter()
                     .filter_map(|arg| match arg {
                         GenericBound::Outlives(Lifetime {
-                            name: LifetimeName::Static,
-                            span,
+                            res: LifetimeName::Static,
+                            ident,
                             ..
-                        }) => Some(*span),
+                        }) => Some(ident.span),
                         _ => None,
                     })
                     .next()
@@ -342,10 +342,10 @@ pub fn suggest_new_region_bound(
                     .bounds
                     .iter()
                     .filter_map(|arg| match arg {
-                        GenericBound::Outlives(Lifetime { name, span, .. })
-                            if name.ident().to_string() == lifetime_name =>
+                        GenericBound::Outlives(Lifetime { ident, .. })
+                            if ident.name.to_string() == lifetime_name =>
                         {
-                            Some(*span)
+                            Some(ident.span)
                         }
                         _ => None,
                     })
@@ -361,8 +361,8 @@ pub fn suggest_new_region_bound(
                     );
                 }
             }
-            TyKind::TraitObject(_, lt, _) => match lt.name {
-                LifetimeName::ImplicitObjectLifetimeDefault => {
+            TyKind::TraitObject(_, lt, _) => {
+                if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
                     err.span_suggestion_verbose(
                         fn_return.span.shrink_to_hi(),
                         &format!(
@@ -374,15 +374,14 @@ pub fn suggest_new_region_bound(
                         &plus_lt,
                         Applicability::MaybeIncorrect,
                     );
-                }
-                name if name.ident().to_string() != lifetime_name => {
+                } else if lt.ident.name.to_string() != lifetime_name {
                     // With this check we avoid suggesting redundant bounds. This
                     // would happen if there are nested impl/dyn traits and only
                     // one of them has the bound we'd suggest already there, like
                     // in `impl Foo<X = dyn Bar> + '_`.
                     if let Some(explicit_static) = &explicit_static {
                         err.span_suggestion_verbose(
-                            lt.span,
+                            lt.ident.span,
                             &format!("{} the trait object's {}", consider, explicit_static),
                             &lifetime_name,
                             Applicability::MaybeIncorrect,
@@ -397,8 +396,7 @@ pub fn suggest_new_region_bound(
                         );
                     }
                 }
-                _ => {}
-            },
+            }
             _ => {}
         }
     }
@@ -561,7 +559,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
     fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
         if let TyKind::TraitObject(
             poly_trait_refs,
-            Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. },
             _,
         ) = t.kind
         {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 7fb8ed8c233..93d81125f48 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -52,7 +52,7 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{Abi, VariantIdx};
 use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -2413,8 +2413,34 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
         }
 
         /// Information about why a type cannot be initialized this way.
-        /// Contains an error message and optionally a span to point at.
-        type InitError = (String, Option<Span>);
+        struct InitError {
+            message: String,
+            /// Spans from struct fields and similar that can be obtained from just the type.
+            span: Option<Span>,
+            /// Used to report a trace through adts.
+            nested: Option<Box<InitError>>,
+        }
+        impl InitError {
+            fn spanned(self, span: Span) -> InitError {
+                Self { span: Some(span), ..self }
+            }
+
+            fn nested(self, nested: impl Into<Option<InitError>>) -> InitError {
+                assert!(self.nested.is_none());
+                Self { nested: nested.into().map(Box::new), ..self }
+            }
+        }
+
+        impl<'a> From<&'a str> for InitError {
+            fn from(s: &'a str) -> Self {
+                s.to_owned().into()
+            }
+        }
+        impl From<String> for InitError {
+            fn from(message: String) -> Self {
+                Self { message, span: None, nested: None }
+            }
+        }
 
         /// Test if this constant is all-0.
         fn is_zero(expr: &hir::Expr<'_>) -> bool {
@@ -2470,25 +2496,54 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
 
         fn variant_find_init_error<'tcx>(
             cx: &LateContext<'tcx>,
+            ty: Ty<'tcx>,
             variant: &VariantDef,
             substs: ty::SubstsRef<'tcx>,
             descr: &str,
             init: InitKind,
         ) -> Option<InitError> {
-            variant.fields.iter().find_map(|field| {
-                ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|(mut msg, span)| {
-                    if span.is_none() {
-                        // Point to this field, should be helpful for figuring
-                        // out where the source of the error is.
-                        let span = cx.tcx.def_span(field.did);
-                        write!(&mut msg, " (in this {descr})").unwrap();
-                        (msg, Some(span))
+            let mut field_err = variant.fields.iter().find_map(|field| {
+                ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|mut err| {
+                    if !field.did.is_local() {
+                        err
+                    } else if err.span.is_none() {
+                        err.span = Some(cx.tcx.def_span(field.did));
+                        write!(&mut err.message, " (in this {descr})").unwrap();
+                        err
                     } else {
-                        // Just forward.
-                        (msg, span)
+                        InitError::from(format!("in this {descr}"))
+                            .spanned(cx.tcx.def_span(field.did))
+                            .nested(err)
                     }
                 })
-            })
+            });
+
+            // Check if this ADT has a constrained layout (like `NonNull` and friends).
+            if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) {
+                if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &layout.abi {
+                    let range = scalar.valid_range(cx);
+                    let msg = if !range.contains(0) {
+                        "must be non-null"
+                    } else if init == InitKind::Uninit && !scalar.is_always_valid(cx) {
+                        // Prefer reporting on the fields over the entire struct for uninit,
+                        // as the information bubbles out and it may be unclear why the type can't
+                        // be null from just its outside signature.
+
+                        "must be initialized inside its custom valid range"
+                    } else {
+                        return field_err;
+                    };
+                    if let Some(field_err) = &mut field_err {
+                        // Most of the time, if the field error is the same as the struct error,
+                        // the struct error only happens because of the field error.
+                        if field_err.message.contains(msg) {
+                            field_err.message = format!("because {}", field_err.message);
+                        }
+                    }
+                    return Some(InitError::from(format!("`{ty}` {msg}")).nested(field_err));
+                }
+            }
+            field_err
         }
 
         /// Return `Some` only if we are sure this type does *not*
@@ -2501,63 +2556,36 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             use rustc_type_ir::sty::TyKind::*;
             match ty.kind() {
                 // Primitive types that don't like 0 as a value.
-                Ref(..) => Some(("references must be non-null".to_string(), None)),
-                Adt(..) if ty.is_box() => Some(("`Box` must be non-null".to_string(), None)),
-                FnPtr(..) => Some(("function pointers must be non-null".to_string(), None)),
-                Never => Some(("the `!` type has no valid value".to_string(), None)),
+                Ref(..) => Some("references must be non-null".into()),
+                Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()),
+                FnPtr(..) => Some("function pointers must be non-null".into()),
+                Never => Some("the `!` type has no valid value".into()),
                 RawPtr(tm) if matches!(tm.ty.kind(), Dynamic(..)) =>
                 // raw ptr to dyn Trait
                 {
-                    Some(("the vtable of a wide raw pointer must be non-null".to_string(), None))
+                    Some("the vtable of a wide raw pointer must be non-null".into())
                 }
                 // Primitive types with other constraints.
                 Bool if init == InitKind::Uninit => {
-                    Some(("booleans must be either `true` or `false`".to_string(), None))
+                    Some("booleans must be either `true` or `false`".into())
                 }
                 Char if init == InitKind::Uninit => {
-                    Some(("characters must be a valid Unicode codepoint".to_string(), None))
+                    Some("characters must be a valid Unicode codepoint".into())
                 }
                 Int(_) | Uint(_) if init == InitKind::Uninit => {
-                    Some(("integers must not be uninitialized".to_string(), None))
-                }
-                Float(_) if init == InitKind::Uninit => {
-                    Some(("floats must not be uninitialized".to_string(), None))
+                    Some("integers must be initialized".into())
                 }
+                Float(_) if init == InitKind::Uninit => Some("floats must be initialized".into()),
                 RawPtr(_) if init == InitKind::Uninit => {
-                    Some(("raw pointers must not be uninitialized".to_string(), None))
+                    Some("raw pointers must be initialized".into())
                 }
                 // Recurse and checks for some compound types. (but not unions)
                 Adt(adt_def, substs) if !adt_def.is_union() => {
-                    // First check if this ADT has a layout attribute (like `NonNull` and friends).
-                    use std::ops::Bound;
-                    match cx.tcx.layout_scalar_valid_range(adt_def.did()) {
-                        // We exploit here that `layout_scalar_valid_range` will never
-                        // return `Bound::Excluded`.  (And we have tests checking that we
-                        // handle the attribute correctly.)
-                        // We don't add a span since users cannot declare such types anyway.
-                        (Bound::Included(lo), Bound::Included(hi)) if 0 < lo && lo < hi => {
-                            return Some((format!("`{}` must be non-null", ty), None));
-                        }
-                        (Bound::Included(lo), Bound::Unbounded) if 0 < lo => {
-                            return Some((format!("`{}` must be non-null", ty), None));
-                        }
-                        (Bound::Included(_), _) | (_, Bound::Included(_))
-                            if init == InitKind::Uninit =>
-                        {
-                            return Some((
-                                format!(
-                                    "`{}` must be initialized inside its custom valid range",
-                                    ty,
-                                ),
-                                None,
-                            ));
-                        }
-                        _ => {}
-                    }
                     // Handle structs.
                     if adt_def.is_struct() {
                         return variant_find_init_error(
                             cx,
+                            ty,
                             adt_def.non_enum_variant(),
                             substs,
                             "struct field",
@@ -2581,13 +2609,14 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                         Some((variant, definitely_inhabited))
                     });
                     let Some(first_variant) = potential_variants.next() else {
-                        return Some(("enums with no inhabited variants have no valid value".to_string(), Some(span)));
+                        return Some(InitError::from("enums with no inhabited variants have no valid value").spanned(span));
                     };
                     // So we have at least one potentially inhabited variant. Might we have two?
                     let Some(second_variant) = potential_variants.next() else {
                         // There is only one potentially inhabited variant. So we can recursively check that variant!
                         return variant_find_init_error(
                             cx,
+                            ty,
                             &first_variant.0,
                             substs,
                             "field of the only potentially inhabited enum variant",
@@ -2605,10 +2634,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                                 .filter(|(_variant, definitely_inhabited)| *definitely_inhabited)
                                 .count();
                         if definitely_inhabited > 1 {
-                            return Some((
-                                "enums with multiple inhabited variants have to be initialized to a variant".to_string(),
-                                Some(span),
-                            ));
+                            return Some(InitError::from(
+                                "enums with multiple inhabited variants have to be initialized to a variant",
+                            ).spanned(span));
                         }
                     }
                     // We couldn't find anything wrong here.
@@ -2637,8 +2665,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             // using zeroed or uninitialized memory.
             // We are extremely conservative with what we warn about.
             let conjured_ty = cx.typeck_results().expr_ty(expr);
-            if let Some((msg, span)) =
-                with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
+            if let Some(mut err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
             {
                 // FIXME(davidtwco): make translatable
                 cx.struct_span_lint(
@@ -2664,10 +2691,17 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                             "help: use `MaybeUninit<T>` instead, \
                             and only call `assume_init` after initialization is done",
                         );
-                        if let Some(span) = span {
-                            lint.span_note(span, &msg);
-                        } else {
-                            lint.note(&msg);
+                        loop {
+                            if let Some(span) = err.span {
+                                lint.span_note(span, &err.message);
+                            } else {
+                                lint.note(&err.message);
+                            }
+                            if let Some(e) = err.nested {
+                                err = *e;
+                            } else {
+                                break;
+                            }
                         }
                         lint
                     },
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 11e4650cb4b..293f1c5c471 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -272,11 +272,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
             .args
             .iter()
             .filter_map(|arg| {
-                if let GenericArg::Lifetime(lt) = arg {
-                    Some(lt.name.ident().to_string())
-                } else {
-                    None
-                }
+                if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
             })
             .collect::<Vec<_>>();
 
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 01bface718a..cf1d82f4c06 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
             .args
             .iter()
             .map(|arg| match arg {
-                GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
+                GenericArg::Lifetime(lt) => lt.to_string(),
                 GenericArg::Type(ty) => {
                     cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into())
                 }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index d4456adf201..4617c17b153 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1058,7 +1058,7 @@ impl<'hir> Map<'hir> {
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
             Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
-            Node::Lifetime(lifetime) => lifetime.span,
+            Node::Lifetime(lifetime) => lifetime.ident.span,
             Node::GenericParam(param) => param.span,
             Node::Infer(i) => i.span,
             Node::Local(local) => local.span,
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 7436f0f6f4d..f3186e1c30c 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -245,6 +245,18 @@ impl ScalarInt {
         self.to_bits(size)
     }
 
+    // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
+    // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
+    // value of the `ScalarInt` in that case.
+    #[inline]
+    pub fn try_to_bool(self) -> Result<bool, Size> {
+        match self.try_to_u8()? {
+            0 => Ok(false),
+            1 => Ok(true),
+            _ => Err(self.size()),
+        }
+    }
+
     // Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
     // in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in
     // that case.
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 69f50df6235..b087ff4bf53 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -397,7 +397,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
             hir::TyKind::TraitObject(
                 _,
                 hir::Lifetime {
-                    name:
+                    res:
                         hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
                     ..
                 },
@@ -421,10 +421,9 @@ pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'
 
 impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
     fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
-        if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
-            lt.name
+        if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
         {
-            self.0.push(lt.span);
+            self.0.push(lt.ident.span);
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 19754d1453f..a8da93e4c69 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -3,7 +3,7 @@ use crate::ty::{EarlyBinder, SubstsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
 
 use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
@@ -78,6 +78,15 @@ impl GenericParamDef {
         }
     }
 
+    pub fn is_anonymous_lifetime(&self) -> bool {
+        match self.kind {
+            GenericParamDefKind::Lifetime => {
+                self.name == kw::UnderscoreLifetime || self.name == kw::Empty
+            }
+            _ => false,
+        }
+    }
+
     pub fn default_value<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 94dc029e6c0..595b73986a8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -208,6 +208,8 @@ pub struct ResolverAstLowering {
     /// A small map keeping true kinds of built-in macros that appear to be fn-like on
     /// the surface (`macro` items in libcore), but are actually attributes or derives.
     pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
+    /// List functions and methods for which lifetime elision was successful.
+    pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -529,7 +531,7 @@ impl ty::EarlyBoundRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).
     pub fn has_name(&self) -> bool {
-        self.name != kw::UnderscoreLifetime
+        self.name != kw::UnderscoreLifetime && self.name != kw::Empty
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d5e196b2e9f..44b85098630 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -681,25 +681,20 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Str => p!("str"),
             ty::Generator(did, substs, movability) => {
-                // FIXME(swatinem): async constructs used to be pretty printed
-                // as `impl Future` previously due to the `from_generator` wrapping.
-                // lets special case this here for now to avoid churn in diagnostics.
-                let generator_kind = self.tcx().generator_kind(did);
-                if matches!(generator_kind, Some(hir::GeneratorKind::Async(..))) {
-                    let return_ty = substs.as_generator().return_ty();
-                    p!(write("impl Future<Output = {}>", return_ty));
-
-                    return Ok(self);
-                }
-
                 p!(write("["));
-                match movability {
-                    hir::Movability::Movable => {}
-                    hir::Movability::Static => p!("static "),
+                let generator_kind = self.tcx().generator_kind(did).unwrap();
+                let should_print_movability =
+                    self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen;
+
+                if should_print_movability {
+                    match movability {
+                        hir::Movability::Movable => {}
+                        hir::Movability::Static => p!("static "),
+                    }
                 }
 
                 if !self.should_print_verbose() {
-                    p!("generator");
+                    p!(write("{}", generator_kind));
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         let span = self.tcx().def_span(did);
@@ -1977,17 +1972,13 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
 
         match *region {
-            ty::ReEarlyBound(ref data) => {
-                data.name != kw::Empty && data.name != kw::UnderscoreLifetime
-            }
+            ty::ReEarlyBound(ref data) => data.has_name(),
 
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
-                if let ty::BrNamed(_, name) = br {
-                    if name != kw::Empty && name != kw::UnderscoreLifetime {
-                        return true;
-                    }
+                if br.is_named() {
+                    return true;
                 }
 
                 if let Some((region, _)) = highlight.highlight_bound_region {
@@ -2063,11 +2054,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
-                if let ty::BrNamed(_, name) = br {
-                    if name != kw::Empty && name != kw::UnderscoreLifetime {
-                        p!(write("{}", name));
-                        return Ok(self);
-                    }
+                if let ty::BrNamed(_, name) = br && br.is_named() {
+                    p!(write("{}", name));
+                    return Ok(self);
                 }
 
                 if let Some((region, counter)) = highlight.highlight_bound_region {
@@ -2280,7 +2269,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 
                         (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name))
                     }
-                    ty::BrNamed(def_id, kw::UnderscoreLifetime) => {
+                    ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => {
                         let name = next_name(&self);
 
                         if let Some(lt_idx) = lifetime_idx {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index ea959be2e4e..1e1a566de44 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -83,7 +83,9 @@ pub struct BoundRegion {
 impl BoundRegionKind {
     pub fn is_named(&self) -> bool {
         match *self {
-            BoundRegionKind::BrNamed(_, name) => name != kw::UnderscoreLifetime,
+            BoundRegionKind::BrNamed(_, name) => {
+                name != kw::UnderscoreLifetime && name != kw::Empty
+            }
             _ => false,
         }
     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 8555e4c8626..2d2408c061e 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1838,6 +1838,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
         let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
         let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
+            self.r.lifetime_elision_allowed.insert(fn_id);
             LifetimeRibKind::Elided(*res)
         } else {
             LifetimeRibKind::ElisionFailure
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ad05d4f1446..82214d4c3c4 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1036,6 +1036,8 @@ pub struct Resolver<'a> {
     /// they are declared in the static array generated by proc_macro_harness.
     proc_macros: Vec<NodeId>,
     confused_type_with_std_module: FxHashMap<Span, Span>,
+    /// Whether lifetime elision was successful.
+    lifetime_elision_allowed: FxHashSet<NodeId>,
 
     effective_visibilities: EffectiveVisibilities,
 }
@@ -1354,6 +1356,7 @@ impl<'a> Resolver<'a> {
             trait_impls: Default::default(),
             proc_macros: Default::default(),
             confused_type_with_std_module: Default::default(),
+            lifetime_elision_allowed: Default::default(),
             effective_visibilities: Default::default(),
         };
 
@@ -1448,6 +1451,7 @@ impl<'a> Resolver<'a> {
             def_id_to_node_id: self.def_id_to_node_id,
             trait_map: self.trait_map,
             builtin_macro_kinds: self.builtin_macro_kinds,
+            lifetime_elision_allowed: self.lifetime_elision_allowed,
         };
         ResolverOutputs { definitions, global_ctxt, ast_lowering }
     }
@@ -1491,6 +1495,7 @@ impl<'a> Resolver<'a> {
             def_id_to_node_id: self.def_id_to_node_id.clone(),
             trait_map: self.trait_map.clone(),
             builtin_macro_kinds: self.builtin_macro_kinds.clone(),
+            lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
         };
         ResolverOutputs { definitions, global_ctxt, ast_lowering }
     }
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index 74048ff7da3..9197a28c188 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -167,7 +167,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
             }
             hir::TyKind::Rptr(ref lifetime, ref mt) => {
                 let mut prefix = "&".to_owned();
-                prefix.push_str(&lifetime.name.ident().to_string());
+                prefix.push_str(&lifetime.ident.to_string());
                 prefix.push(' ');
                 if mt.mutbl.is_mut() {
                     prefix.push_str("mut ");
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index 5987fb2a198..47aa4dfba42 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -41,7 +41,7 @@ pub fn analyze_source_file(
 }
 
 cfg_if::cfg_if! {
-    if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64")))] {
+    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
         fn analyze_source_file_dispatch(src: &str,
                                     source_file_start_pos: BytePos,
                                     lines: &mut Vec<BytePos>,
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index bbeabdb55a7..f5555846d20 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -34,7 +34,7 @@ impl CrateNum {
 
 impl fmt::Display for CrateNum {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.private, f)
+        fmt::Display::fmt(&self.as_u32(), f)
     }
 }
 
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 191186af6fa..99a8b03fa39 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -76,7 +76,7 @@ pub struct ExpnId {
 impl fmt::Debug for ExpnId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Generate crate_::{{expn_}}.
-        write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.private)
+        write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.as_u32())
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index da6ca30cc9a..b7728b054e4 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2673,7 +2673,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let sp = self.tcx.def_span(def_id);
 
                                 // Special-case this to say "async block" instead of `[static generator]`.
-                                let kind = tcx.generator_kind(def_id).unwrap();
+                                let kind = tcx.generator_kind(def_id).unwrap().descr();
                                 err.span_note(
                                     sp,
                                     &format!("required because it's used within this {}", kind),
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 7a1cc1e9e6d..fbc055b5d23 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -325,8 +325,8 @@ fn layout_of_uncached<'tcx>(
 
                 // Extract the number of elements from the layout of the array field:
                 let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
-                        return Err(LayoutError::Unknown(ty));
-                    };
+                    return Err(LayoutError::Unknown(ty));
+                };
 
                 (*e_ty, *count, true)
             } else {
@@ -351,14 +351,14 @@ fn layout_of_uncached<'tcx>(
             // Compute the ABI of the element type:
             let e_ly = cx.layout_of(e_ty)?;
             let Abi::Scalar(e_abi) = e_ly.abi else {
-                    // This error isn't caught in typeck, e.g., if
-                    // the element type of the vector is generic.
-                    tcx.sess.fatal(&format!(
-                        "monomorphising SIMD type `{}` with a non-primitive-scalar \
-                        (integer/float/pointer) element type `{}`",
-                        ty, e_ty
-                    ))
-                };
+                // This error isn't caught in typeck, e.g., if
+                // the element type of the vector is generic.
+                tcx.sess.fatal(&format!(
+                    "monomorphising SIMD type `{}` with a non-primitive-scalar \
+                    (integer/float/pointer) element type `{}`",
+                    ty, e_ty
+                ))
+            };
 
             // Compute the size and alignment of the vector:
             let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?;
@@ -597,8 +597,8 @@ fn generator_layout<'tcx>(
     let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
 
     let Some(info) = tcx.generator_layout(def_id) else {
-            return Err(LayoutError::Unknown(ty));
-        };
+        return Err(LayoutError::Unknown(ty));
+    };
     let (ineligible_locals, assignments) = generator_saved_local_eligibility(&info);
 
     // Build a prefix layout, including "promoting" all ineligible
@@ -701,8 +701,8 @@ fn generator_layout<'tcx>(
             variant.variants = Variants::Single { index };
 
             let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else {
-                    bug!();
-                };
+                bug!();
+            };
 
             // Now, stitch the promoted and variant-only fields back together in
             // the order they are mentioned by our GeneratorLayout.
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index ec35914f1e3..383bdc7b6e2 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1113,7 +1113,10 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// # Stability
 ///
 /// The discriminant of an enum variant may change if the enum definition changes. A discriminant
-/// of some variant will not change between compilations with the same compiler.
+/// of some variant will not change between compilations with the same compiler. See the [Reference]
+/// for more information.
+///
+/// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
 ///
 /// # Examples
 ///
@@ -1129,6 +1132,62 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2)));
 /// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3)));
 /// ```
+///
+/// ## Accessing the numeric value of the discriminant
+///
+/// Note that it is *undefined behavior* to [`transmute`] from [`Discriminant`] to a primitive!
+///
+/// If an enum has only unit variants, then the numeric value of the discriminant can be accessed
+/// with an [`as`] cast:
+///
+/// ```
+/// enum Enum {
+///     Foo,
+///     Bar,
+///     Baz,
+/// }
+///
+/// assert_eq!(0, Enum::Foo as isize);
+/// assert_eq!(1, Enum::Bar as isize);
+/// assert_eq!(2, Enum::Baz as isize);
+/// ```
+///
+/// If an enum has opted-in to having a [primitive representation] for its discriminant,
+/// then it's possible to use pointers to read the memory location storing the discriminant.
+/// That **cannot** be done for enums using the [default representation], however, as it's
+/// undefined what layout the discriminant has and where it's stored — it might not even be
+/// stored at all!
+///
+/// [`as`]: ../../std/keyword.as.html
+/// [primitive representation]: ../../reference/type-layout.html#primitive-representations
+/// [default representation]: ../../reference/type-layout.html#the-default-representation
+/// ```
+/// #[repr(u8)]
+/// enum Enum {
+///     Unit,
+///     Tuple(bool),
+///     Struct { a: bool },
+/// }
+///
+/// impl Enum {
+///     fn discriminant(&self) -> u8 {
+///         // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union`
+///         // between `repr(C)` structs, each of which has the `u8` discriminant as its first
+///         // field, so we can read the discriminant without offsetting the pointer.
+///         unsafe { *<*const _>::from(self).cast::<u8>() }
+///     }
+/// }
+///
+/// let unit_like = Enum::Unit;
+/// let tuple_like = Enum::Tuple(true);
+/// let struct_like = Enum::Struct { a: false };
+/// assert_eq!(0, unit_like.discriminant());
+/// assert_eq!(1, tuple_like.discriminant());
+/// assert_eq!(2, struct_like.discriminant());
+///
+/// // ⚠️ This is undefined behavior. Don't do this. ⚠️
+/// // assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) });
+/// ```
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")]
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index e8e7c51cb9b..3edbe728077 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -4,7 +4,7 @@ use crate::ptr;
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
-#[cfg(all(any(
+#[cfg(any(
     target_arch = "x86",
     target_arch = "arm",
     target_arch = "mips",
@@ -16,9 +16,9 @@ use crate::ptr;
     target_arch = "hexagon",
     all(target_arch = "riscv32", not(target_os = "espidf")),
     all(target_arch = "xtensa", not(target_os = "espidf")),
-)))]
+))]
 pub const MIN_ALIGN: usize = 8;
-#[cfg(all(any(
+#[cfg(any(
     target_arch = "x86_64",
     target_arch = "aarch64",
     target_arch = "mips64",
@@ -26,13 +26,13 @@ pub const MIN_ALIGN: usize = 8;
     target_arch = "sparc64",
     target_arch = "riscv64",
     target_arch = "wasm64",
-)))]
+))]
 pub const MIN_ALIGN: usize = 16;
 // The allocator on the esp-idf platform guarantees 4 byte alignment.
-#[cfg(all(any(
+#[cfg(any(
     all(target_arch = "riscv32", target_os = "espidf"),
     all(target_arch = "xtensa", target_os = "espidf"),
-)))]
+))]
 pub const MIN_ALIGN: usize = 4;
 
 pub unsafe fn realloc_fallback(
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 776d73b98c4..1d526022812 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -97,13 +97,7 @@ fn main() {
         // This... is a bit of a hack how we detect this. Ideally this
         // information should be encoded in the crate I guess? Would likely
         // require an RFC amendment to RFC 1513, however.
-        //
-        // `compiler_builtins` are unconditionally compiled with panic=abort to
-        // workaround undefined references to `rust_eh_unwind_resume` generated
-        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
-        if crate_name == Some("panic_abort")
-            || crate_name == Some("compiler_builtins") && stage != "0"
-        {
+        if crate_name == Some("panic_abort") {
             cmd.arg("-C").arg("panic=abort");
         }
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 251431a15eb..cff5fd8c5b0 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -644,6 +644,7 @@ impl<'a> Builder<'a> {
                 test::CrateLibrustc,
                 test::CrateRustdoc,
                 test::CrateRustdocJsonTypes,
+                test::CrateJsonDocLint,
                 test::Linkcheck,
                 test::TierCheck,
                 test::ReplacePlaceholderTest,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index a69979d7f07..39cedfdac5f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -91,6 +91,42 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct CrateJsonDocLint {
+    host: TargetSelection,
+}
+
+impl Step for CrateJsonDocLint {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/jsondoclint")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(CrateJsonDocLint { host: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let bootstrap_host = builder.config.build;
+        let compiler = builder.compiler(0, bootstrap_host);
+
+        let cargo = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolBootstrap,
+            bootstrap_host,
+            "test",
+            "src/tools/jsondoclint",
+            SourceType::InTree,
+            &[],
+        );
+        try_run(builder, &mut cargo.into());
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Linkcheck {
     host: TargetSelection,
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b0927305eca..582586d33fe 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -182,9 +182,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
         .collect_referenced_late_bound_regions(&poly_trait_ref)
         .into_iter()
         .filter_map(|br| match br {
-            ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => {
-                Some(GenericParamDef::lifetime(name))
-            }
+            ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
             _ => None,
         })
         .collect();
@@ -208,7 +206,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
             return lt;
         }
     }
-    Lifetime(lifetime.name.ident().name)
+    Lifetime(lifetime.ident.name)
 }
 
 pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
@@ -233,16 +231,11 @@ pub(crate) fn clean_middle_const<'tcx>(
 pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
     match *region {
         ty::ReStatic => Some(Lifetime::statik()),
+        _ if !region.has_name() => None,
         ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
-            if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
-        }
-        ty::ReEarlyBound(ref data) => {
-            if data.name != kw::UnderscoreLifetime {
-                Some(Lifetime(data.name))
-            } else {
-                None
-            }
+            Some(Lifetime(name))
         }
+        ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
         ty::ReLateBound(..)
         | ty::ReFree(..)
         | ty::ReVar(..)
@@ -400,7 +393,7 @@ fn clean_projection_predicate<'tcx>(
         .collect_referenced_late_bound_regions(&pred)
         .into_iter()
         .filter_map(|br| match br {
-            ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(Lifetime(name)),
+            ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)),
             _ => None,
         })
         .collect();
@@ -664,7 +657,7 @@ fn clean_ty_generics<'tcx>(
         .params
         .iter()
         .filter_map(|param| match param.kind {
-            ty::GenericParamDefKind::Lifetime if param.name == kw::UnderscoreLifetime => None,
+            ty::GenericParamDefKind::Lifetime if param.is_anonymous_lifetime() => None,
             ty::GenericParamDefKind::Lifetime => Some(clean_generic_param_def(param, cx)),
             ty::GenericParamDefKind::Type { synthetic, .. } => {
                 if param.name == kw::SelfUpper {
@@ -1467,8 +1460,11 @@ fn maybe_expand_private_type_alias<'tcx>(
                 });
                 if let Some(lt) = lifetime {
                     let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                    let cleaned =
-                        if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };
+                    let cleaned = if !lt.is_anonymous() {
+                        clean_lifetime(lt, cx)
+                    } else {
+                        Lifetime::elided()
+                    };
                     substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
                 }
                 indices.lifetimes += 1;
@@ -1531,16 +1527,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         TyKind::Never => Primitive(PrimitiveType::Never),
         TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
         TyKind::Rptr(ref l, ref m) => {
-            // There are two times a `Fresh` lifetime can be created:
-            // 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
-            // 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
-            //    See #59286 for more information.
-            // Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
-            // Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
-            // there's no case where it could cause the function to fail to compile.
-            let elided =
-                l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh));
-            let lifetime = if elided { None } else { Some(clean_lifetime(*l, cx)) };
+            let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) };
             BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
         }
         TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
@@ -1915,7 +1902,7 @@ fn clean_generic_args<'tcx>(
             .args
             .iter()
             .map(|arg| match arg {
-                hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+                hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
                     GenericArg::Lifetime(clean_lifetime(*lt, cx))
                 }
                 hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index cb50c3ae829..81d9c46447a 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -19,7 +19,7 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
-use rustc_target::spec::TargetTriple;
+use rustc_target::spec::{Target, TargetTriple};
 use tempfile::Builder as TempFileBuilder;
 
 use std::env;
@@ -293,6 +293,16 @@ struct UnusedExterns {
     unused_extern_names: Vec<String>,
 }
 
+fn add_exe_suffix(input: String, target: &TargetTriple) -> String {
+    let exe_suffix = match target {
+        TargetTriple::TargetTriple(_) => Target::expect_builtin(target).options.exe_suffix,
+        TargetTriple::TargetJson { contents, .. } => {
+            Target::from_json(contents.parse().unwrap()).unwrap().0.options.exe_suffix
+        }
+    };
+    input + &exe_suffix
+}
+
 fn run_test(
     test: &str,
     crate_name: &str,
@@ -313,7 +323,9 @@ fn run_test(
     let (test, line_offset, supports_color) =
         make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
 
-    let output_file = outdir.path().join("rust_out");
+    // Make sure we emit well-formed executable names for our target.
+    let rust_out = add_exe_suffix("rust_out".to_owned(), &target);
+    let output_file = outdir.path().join(rust_out);
 
     let rustc_binary = rustdoc_options
         .test_builder
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 2a109ffbc60..7230df36c07 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -202,6 +202,7 @@ function loadCss(cssUrl) {
         if (event.ctrlKey || event.altKey || event.metaKey) {
             return;
         }
+        window.hideAllModals(false);
         addClass(getSettingsButton(), "rotate");
         event.preventDefault();
         // Sending request for the CSS and the JS files at the same time so it will
@@ -377,7 +378,7 @@ function loadCss(cssUrl) {
         }
         ev.preventDefault();
         searchState.defocus();
-        window.hidePopoverMenus();
+        window.hideAllModals(true); // true = reset focus for notable traits
     }
 
     function handleShortcut(ev) {
@@ -767,6 +768,7 @@ function loadCss(cssUrl) {
     };
 
     function showSidebar() {
+        window.hideAllModals(false);
         window.rustdocMobileScrollLock();
         const sidebar = document.getElementsByClassName("sidebar")[0];
         addClass(sidebar, "shown");
@@ -843,7 +845,7 @@ function loadCss(cssUrl) {
             // Make this function idempotent.
             return;
         }
-        hideNotable(false);
+        window.hideAllModals(false);
         const ty = e.getAttribute("data-ty");
         const wrapper = document.createElement("div");
         wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>";
@@ -1050,13 +1052,23 @@ function loadCss(cssUrl) {
     }
 
     /**
+     * Hide popover menus, notable trait tooltips, and the sidebar (if applicable).
+     *
+     * Pass "true" to reset focus for notable traits.
+     */
+    window.hideAllModals = function(switchFocus) {
+        hideSidebar();
+        window.hidePopoverMenus();
+        hideNotable(switchFocus);
+    };
+
+    /**
      * Hide all the popover menus.
      */
     window.hidePopoverMenus = function() {
         onEachLazy(document.querySelectorAll(".search-form .popover"), elem => {
             elem.style.display = "none";
         });
-        hideNotable(false);
     };
 
     /**
@@ -1081,7 +1093,7 @@ function loadCss(cssUrl) {
     function showHelp() {
         const menu = getHelpMenu(true);
         if (menu.style.display === "none") {
-            window.hidePopoverMenus();
+            window.hideAllModals();
             menu.style.display = "";
         }
     }
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 5256ae916a7..589bfc79360 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -268,7 +268,7 @@
             event.preventDefault();
             const shouldDisplaySettings = settingsMenu.style.display === "none";
 
-            window.hidePopoverMenus();
+            window.hideAllModals();
             if (shouldDisplaySettings) {
                 displaySettings();
             }
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
index 407992c9f43..436aebf1174 100644
--- a/src/test/run-make/coverage-reports/Makefile
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -132,7 +132,7 @@ include clear_expected_if_blessed
 			--instr-profile="$(TMPDIR)"/$@.profdata \
 			$(call BIN,"$(TMPDIR)"/$@) \
 			$$( \
-				for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
+				for file in $(TMPDIR)/rustdoc-$@/*/rust_out*; do \
 				[ -x "$$file" ] && printf "%s %s " -object $$file; \
 				done \
 			) \
diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml
index aab3b11433e..7e24af47ee8 100644
--- a/src/test/rustdoc-gui/notable-trait.goml
+++ b/src/test/rustdoc-gui/notable-trait.goml
@@ -200,12 +200,14 @@ move-cursor-to: "//*[@class='notable popover']"
 assert-count: ("//*[@class='notable popover']", 1)
 press-key: "Escape"
 assert-count: ("//*[@class='notable popover']", 0)
+assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
 
 // Check that clicking outside works.
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
 assert-count: ("//*[@class='notable popover']", 1)
 click: ".search-input"
 assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
 
 // Check that pressing tab over and over works.
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
@@ -249,3 +251,26 @@ click: "#settings-menu a"
 press-key: "Escape"
 // We ensure we didn't come back to the previous focused item.
 assert-window-property-false: {"scrollY": |scroll|}
+
+// Opening the mobile sidebar should close the popover.
+size: (650, 600)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
+// Clicking a notable popover should close the sidebar.
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+assert-false: "//*[@class='sidebar shown']"
+
+// Also check the focus handling for the help button.
+size: (1100, 600)
+reload:
+assert-count: ("//*[@class='notable popover']", 0)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+click: "#help-button a"
+assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
index fb63ea62a48..c3649dc7bda 100644
--- a/src/test/rustdoc-gui/pocket-menu.goml
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -75,3 +75,24 @@ assert-css: (
 )
 compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Opening the mobile sidebar should close the settings popover.
+size: (650, 600)
+click: "#settings-menu a"
+assert-css: ("#settings-menu .popover", {"display": "block"})
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-css: ("#settings-menu .popover", {"display": "none"})
+// Opening the settings popover should close the sidebar.
+click: "#settings-menu a"
+assert-css: ("#settings-menu .popover", {"display": "block"})
+assert-false: "//*[@class='sidebar shown']"
+
+// Opening the settings popover at start (which async loads stuff) should also close.
+reload:
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-false: "#settings-menu .popover"
+click: "#settings-menu a"
+assert-false: "//*[@class='sidebar shown']"
+wait-for: "#settings-menu .popover"
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index 453873f1b81..38d01f7f612 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -32,6 +32,12 @@ assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In test_docs']/pa
 click: "body"
 assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
+// Open the sidebar menu, and make sure pressing Escape closes it.
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"left": "0px"})
+press-key: "Escape"
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
+
 // Check that the topbar is visible
 assert-property: (".mobile-topbar", {"clientHeight": "45"})
 
@@ -48,23 +54,35 @@ compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topb
 
 // Now checking the background color of the sidebar.
 show-text: true
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
-reload:
-
-// Open the sidebar menu.
-click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(80, 80, 80)", "color": "rgb(221, 221, 221)"})
-
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "ayu"}
-reload:
 
-// Open the sidebar menu.
-click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(20, 25, 31)", "color": "rgb(197, 197, 197)"})
+define-function: (
+    "check-colors",
+    (theme, color, background),
+    [
+        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+        ("reload"),
 
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "light"}
-reload:
+        // Open the sidebar menu.
+        ("click", ".sidebar-menu-toggle"),
+        ("assert-css", (".sidebar", {
+            "background-color": |background|,
+            "color": |color|,
+        })),
+    ],
+)
 
-// Open the sidebar menu.
-click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(245, 245, 245)", "color": "rgb(0, 0, 0)"})
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "color": "rgb(197, 197, 197)",
+    "background": "rgb(20, 25, 31)",
+})
+call-function: ("check-colors", {
+    "theme": "dark",
+    "color": "rgb(221, 221, 221)",
+    "background": "rgb(80, 80, 80)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "color": "rgb(0, 0, 0)",
+    "background": "rgb(245, 245, 245)",
+})
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
index 446212ca767..bc9d127931d 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
@@ -15,7 +15,7 @@ fn return_targets_async_block_not_fn() -> u8 {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+    //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
 }
 
 async fn return_targets_async_block_not_async_fn() -> u8 {
@@ -24,7 +24,7 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+    //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
 }
 
 fn no_break_in_async_block() {
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
index b8ca64fae83..c4487eb840a 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -29,13 +29,13 @@ LL | |
 LL | | }
    | |_^ expected `u8`, found `()`
 
-error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:26:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:12:43
@@ -45,13 +45,13 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:17:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:49:44
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index 774c97966b1..1686153acf9 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -8,8 +8,8 @@ LL |     fun(async {}, async {});
    |         |         arguments to this function are incorrect
    |         the expected `async` block
    |
-   = note: expected `async` block `impl Future<Output = ()>` (`async` block)
-              found `async` block `impl Future<Output = ()>` (`async` block)
+   = note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]`
+              found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
@@ -53,8 +53,8 @@ LL |     fun((async || {})(), (async || {})());
    |     |             the expected `async` closure body
    |     arguments to this function are incorrect
    |
-   = note: expected `async` closure body `impl Future<Output = ()>` (`async` closure body)
-              found `async` closure body `impl Future<Output = ()>` (`async` closure body)
+   = note: expected `async` closure body `[async closure body@$DIR/generator-desc.rs:14:19: 14:21]`
+              found `async` closure body `[async closure body@$DIR/generator-desc.rs:14:36: 14:38]`
 note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
index af99b608ca1..fcba4410ba9 100644
--- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr
+++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
@@ -8,7 +8,7 @@ LL | |         AFuture.await;
 LL | |     });
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*mut ()`
+   = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:18:11: 21:6]`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-67252-unnamed-future.rs:20:16
    |
diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr
index 0e21dba980d..8c2c06da25c 100644
--- a/src/test/ui/async-await/issue-86507.stderr
+++ b/src/test/ui/async-await/issue-86507.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `impl Future<Output = ()>` to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `[async block@$DIR/issue-86507.rs:18:17: 20:18]` to the object type `dyn Future<Output = ()> + Send`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
index a723503776b..ab196dca20c 100644
--- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
@@ -8,7 +8,7 @@ LL | |         bar(Foo(std::ptr::null())).await;
 LL | |     })
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8`
+   = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:16:17: 19:6]`, the trait `Send` is not implemented for `*const u8`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
    |
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index 6f22d2c593a..4804df13340 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -1,4 +1,4 @@
-error[E0277]: `impl Future<Output = u32>` is not a future
+error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
@@ -7,18 +7,18 @@ LL | |     x
 LL | | }
    | | ^
    | | |
-   | |_`impl Future<Output = u32>` is not a future
+   | |_`[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
    |   required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
-   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
+   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
    |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
-error[E0277]: the size for values of type `<impl Future<Output = u32> as Future>::Output` cannot be known at compilation time
+error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
@@ -27,23 +27,23 @@ LL | |     x
 LL | | }
    | |_^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `<impl Future<Output = u32> as Future>::Output`
+   = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
    |                              ^ required by this bound in `identity_future`
 
-error[E0277]: `impl Future<Output = u32>` is not a future
+error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:25
    |
 LL | async fn foo(x: u32) -> u32 {
-   |                         ^^^ `impl Future<Output = u32>` is not a future
+   |                         ^^^ `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
    |
-   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
-   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
+   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 
-error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
+error[E0280]: the requirement `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output == u32` is not satisfied
   --> $DIR/async.rs:7:25
    |
 LL | async fn foo(x: u32) -> u32 {
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr
index 9deb9b26588..8278edabe3a 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr
@@ -11,7 +11,7 @@ LL |     type Y<'a>;
    |          ^ --
 help: add missing lifetime argument
    |
-LL |     fn f2<'a>(arg: Box<dyn X<Y<'a, 1> = &'a ()>>) {}
+LL |     fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {}
    |                                +++
 
 error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr
index b97b6faa3be..bc1141b16c5 100644
--- a/src/test/ui/constructor-lifetime-args.stderr
+++ b/src/test/ui/constructor-lifetime-args.stderr
@@ -13,8 +13,8 @@ LL | struct S<'a, 'b>(&'a u8, &'b u8);
    |        ^ --  --
 help: add missing lifetime argument
    |
-LL |     S::<'static, 'b>(&0, &0);
-   |                ++++
+LL |     S::<'static, 'static>(&0, &0);
+   |                +++++++++
 
 error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
   --> $DIR/constructor-lifetime-args.rs:19:5
@@ -45,8 +45,8 @@ LL | enum E<'a, 'b> {
    |      ^ --  --
 help: add missing lifetime argument
    |
-LL |     E::V::<'static, 'b>(&0);
-   |                   ++++
+LL |     E::V::<'static, 'static>(&0);
+   |                   +++++++++
 
 error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
   --> $DIR/constructor-lifetime-args.rs:24:8
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
index dbd05b8f424..b24e0cc37aa 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
@@ -65,6 +65,17 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
                14 00 00 00                                     │ ....
            }
 
-error: aborting due to 7 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:50:1
+   |
+LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |
+   = 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: 4) {
+               00 00 00 00 ╾─alloc26─╼                         │ ....╾──╼
+           }
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
index 5a1ac09bd35..92b8d017c0b 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
@@ -65,6 +65,17 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
                14 00 00 00                                     │ ....
            }
 
-error: aborting due to 7 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:50:1
+   |
+LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |
+   = 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: 16, align: 8) {
+               00 00 00 00 00 00 00 00 ╾───────alloc26───────╼ │ ........╾──────╼
+           }
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index d22a99cd01e..49092582267 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -1,5 +1,5 @@
 // stderr-per-bitwidth
-#![feature(rustc_attrs)]
+#![feature(rustc_attrs, ptr_metadata)]
 #![allow(invalid_value)] // make sure we cannot allow away the errors tested here
 
 use std::mem;
@@ -47,4 +47,11 @@ struct RestrictedRange2(u32);
 const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
 //~^ ERROR it is undefined behavior to use this value
 
+const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+//~^ ERROR it is undefined behavior to use this value
+    let x: &dyn Send = &42;
+    let meta = std::ptr::metadata(x);
+    mem::transmute((0_usize, meta))
+};
+
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 63639729a2a..8b4d845b30e 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -40,6 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+note: in this struct field
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 note: enums with no inhabited variants have no valid value
   --> $DIR/validate_uninhabited_zsts.rs:13:5
    |
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 63639729a2a..8b4d845b30e 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -40,6 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+note: in this struct field
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 note: enums with no inhabited variants have no valid value
   --> $DIR/validate_uninhabited_zsts.rs:13:5
    |
diff --git a/src/test/ui/generator/clone-impl-async.rs b/src/test/ui/generator/clone-impl-async.rs
index 83c51526b7b..9e9b59d3633 100644
--- a/src/test/ui/generator/clone-impl-async.rs
+++ b/src/test/ui/generator/clone-impl-async.rs
@@ -15,42 +15,42 @@ fn main() {
         drop(non_clone);
     };
     check_copy(&inner_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&inner_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let non_clone = NonClone;
     let outer_non_clone = async move {
         drop(non_clone);
     };
     check_copy(&outer_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&outer_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let maybe_copy_clone = async move {};
     check_copy(&maybe_copy_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&maybe_copy_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let inner_non_clone_fn = the_inner_non_clone_fn();
     check_copy(&inner_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&inner_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let outer_non_clone_fn = the_outer_non_clone_fn(NonClone);
     check_copy(&outer_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&outer_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let maybe_copy_clone_fn = the_maybe_copy_clone_fn();
     check_copy(&maybe_copy_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&maybe_copy_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 }
 
 async fn the_inner_non_clone_fn() {
@@ -64,8 +64,7 @@ async fn the_outer_non_clone_fn(non_clone: NonClone) {
     drop(non_clone);
 }
 
-async fn the_maybe_copy_clone_fn() {
-}
+async fn the_maybe_copy_clone_fn() {}
 
 fn check_copy<T: Copy>(_x: &T) {}
 fn check_clone<T: Clone>(_x: &T) {}
diff --git a/src/test/ui/generator/clone-impl-async.stderr b/src/test/ui/generator/clone-impl-async.stderr
index cbb58d2af18..9854728876f 100644
--- a/src/test/ui/generator/clone-impl-async.stderr
+++ b/src/test/ui/generator/clone-impl-async.stderr
@@ -1,83 +1,83 @@
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:17:16
    |
 LL |     check_copy(&inner_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:19:17
    |
 LL |     check_clone(&inner_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:26:16
    |
 LL |     check_copy(&outer_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:28:17
    |
 LL |     check_clone(&outer_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:32:16
    |
 LL |     check_copy(&maybe_copy_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:34:17
    |
 LL |     check_clone(&maybe_copy_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -91,7 +91,7 @@ LL |     check_copy(&inner_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -105,7 +105,7 @@ LL |     check_clone(&inner_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -119,7 +119,7 @@ LL |     check_copy(&outer_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -133,7 +133,7 @@ LL |     check_clone(&outer_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -147,7 +147,7 @@ LL |     check_copy(&maybe_copy_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -161,7 +161,7 @@ LL |     check_clone(&maybe_copy_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
index 20f35c3c137..a9996123f23 100644
--- a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
+++ b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr
@@ -11,7 +11,7 @@ LL |     type Assoc<'a> where Self: 'a;
    |          ^^^^^ --
 help: add missing lifetime argument
    |
-LL |     fn g(&self) -> Self::Assoc<'a>;
+LL |     fn g(&self) -> Self::Assoc<'_>;
    |                          ~~~~~~~~~
 
 error[E0107]: missing generics for associated type `Trait::Assoc`
@@ -27,7 +27,7 @@ LL |     type Assoc<'a> where Self: 'a;
    |          ^^^^^ --
 help: add missing lifetime argument
    |
-LL |     fn g(&self) -> Self::Assoc<'a> {
+LL |     fn g(&self) -> Self::Assoc<'_> {
    |                          ~~~~~~~~~
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
index e55a21e19f0..165779796e0 100644
--- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
+++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -36,7 +36,7 @@ LL |   type Y<'a>;
    |        ^ --
 help: add missing lifetime argument
    |
-LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {}
+LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {}
    |                             +++
 
 error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
@@ -66,7 +66,7 @@ LL |   type Y<'a>;
    |        ^ --
 help: add missing lifetime argument
    |
-LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {}
+LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {}
    |                             ++
 
 error: aborting due to 6 previous errors
diff --git a/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr
index ba798084673..9e21c567c73 100644
--- a/src/test/ui/generic-associated-types/issue-81862.stderr
+++ b/src/test/ui/generic-associated-types/issue-81862.stderr
@@ -11,7 +11,7 @@ LL |     type Item<'a>;
    |          ^^^^ --
 help: add missing lifetime argument
    |
-LL |     fn next(&mut self) -> Option<Self::Item<'a>>;
+LL |     fn next(&mut self) -> Option<Self::Item<'_>>;
    |                                        ~~~~~~~~
 
 error: aborting due to previous error
diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
index 0ad1f1f8c4d..752587c25a7 100644
--- a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
+++ b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr
@@ -11,7 +11,7 @@ LL |     type Y<'a, 'b>;
    |          ^ --  --
 help: add missing lifetime arguments
    |
-LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {}
+LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
    |                                ~~~~~~~~~
 
 error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
@@ -47,7 +47,7 @@ LL | struct Foo<'a, 'b, 'c> {
    |        ^^^ --  --  --
 help: add missing lifetime arguments
    |
-LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {}
+LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {}
    |                      ++++++++
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
index e00a414efb9..0a09ec5dc49 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
@@ -11,7 +11,7 @@ LL |     type Y<'a>;
    |          ^ --
 help: add missing lifetime argument
    |
-LL |   fn f2<'a>(arg : Box<dyn X<Y<'a, 1> = &'a ()>>) {}
+LL |   fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {}
    |                               +++
 
 error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr
index 388c23fc24f..0475eb908a7 100644
--- a/src/test/ui/generics/wrong-number-of-args.stderr
+++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -812,8 +812,8 @@ LL |         trait GenericLifetimeLifetimeAT<'a, 'b> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^ --  --
 help: add missing lifetime argument
    |
-LL |         type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
-   |                                                           ++++
+LL |         type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'static, AssocTy=()>>;
+   |                                                           +++++++++
 
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:287:26
@@ -846,8 +846,8 @@ LL |         trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --  --
 help: add missing lifetime argument
    |
-LL |         type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, AssocTy=()>>;
-   |                                                               ++++
+LL |         type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, AssocTy=()>>;
+   |                                                               +++++++++
 
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:294:26
@@ -880,8 +880,8 @@ LL |         trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --  --
 help: add missing lifetime argument
    |
-LL |         type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, (), AssocTy=()>>;
-   |                                                               ++++
+LL |         type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, (), AssocTy=()>>;
+   |                                                               +++++++++
 
 error[E0107]: missing generics for struct `HashMap`
   --> $DIR/wrong-number-of-args.rs:310:18
diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs
index 3ffce85e61b..91811df93cd 100644
--- a/src/test/ui/impl-trait/issue-55872-3.rs
+++ b/src/test/ui/impl-trait/issue-55872-3.rs
@@ -12,7 +12,7 @@ pub trait Bar {
 impl<S> Bar for S {
     type E = impl std::marker::Copy;
     fn foo<T>() -> Self::E {
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied [E0277]
+        //~^ ERROR : Copy` is not satisfied [E0277]
         async {}
     }
 }
diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr
index 6ab540e8751..c6e10f0f350 100644
--- a/src/test/ui/impl-trait/issue-55872-3.stderr
+++ b/src/test/ui/impl-trait/issue-55872-3.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]: Copy` is not satisfied
   --> $DIR/issue-55872-3.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
index 9ee1ba3d3b4..78233f300bd 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.rs
+++ b/src/test/ui/impl-trait/issues/issue-78722.rs
@@ -7,7 +7,7 @@ type F = impl core::future::Future<Output = u8>;
 struct Bug {
     V1: [(); {
         fn concrete_use() -> F {
-            //~^ ERROR expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
+            //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
             async {}
         }
         let f: F = async { 1 };
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
index a96994f5a7f..c00df8087e8 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.stderr
+++ b/src/test/ui/impl-trait/issues/issue-78722.stderr
@@ -16,7 +16,7 @@ LL |         let f: F = async { 1 };
 LL |     }],
    |     - value is dropped here
 
-error[E0271]: expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
+error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()`
   --> $DIR/issue-78722.rs:9:30
    |
 LL |         fn concrete_use() -> F {
diff --git a/src/test/ui/layout/valid_range_oob.rs b/src/test/ui/layout/valid_range_oob.rs
new file mode 100644
index 00000000000..74aa47fe405
--- /dev/null
+++ b/src/test/ui/layout/valid_range_oob.rs
@@ -0,0 +1,15 @@
+// failure-status: 101
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// rustc-env:RUST_BACKTRACE=0
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_end(257)]
+struct Foo(i8);
+
+// Need to do in a constant, as runtime codegen
+// does not compute the layout of `Foo` in check builds.
+const FOO: Foo = unsafe { Foo(1) };
+
+fn main() {}
diff --git a/src/test/ui/layout/valid_range_oob.stderr b/src/test/ui/layout/valid_range_oob.stderr
new file mode 100644
index 00000000000..7398f01643f
--- /dev/null
+++ b/src/test/ui/layout/valid_range_oob.stderr
@@ -0,0 +1,6 @@
+error: internal compiler error: unexpected panic
+
+query stack during panic:
+#0 [layout_of] computing layout of `Foo`
+#1 [eval_to_allocation_raw] const-evaluating + checking `FOO`
+end of query stack
diff --git a/src/test/ui/lint/invalid_value.stderr b/src/test/ui/lint/invalid_value.stderr
index 76afb765f0f..5370660d6c1 100644
--- a/src/test/ui/lint/invalid_value.stderr
+++ b/src/test/ui/lint/invalid_value.stderr
@@ -34,7 +34,8 @@ LL |         let _val: Wrap<&'static T> = mem::zeroed();
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Wrap<&T>` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -49,7 +50,8 @@ LL |         let _val: Wrap<&'static T> = mem::uninitialized();
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Wrap<&T>` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -97,7 +99,7 @@ LL |         let _val: (i32, !) = mem::uninitialized();
    |                              this code causes undefined behavior when executed
    |                              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: integers must not be uninitialized
+   = note: integers must be initialized
 
 error: the type `Void` does not permit zero-initialization
   --> $DIR/invalid_value.rs:71:26
@@ -160,7 +162,8 @@ LL |         let _val: Ref = mem::zeroed();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Ref` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:14:12
    |
 LL | struct Ref(&'static i32);
@@ -175,7 +178,8 @@ LL |         let _val: Ref = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Ref` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:14:12
    |
 LL | struct Ref(&'static i32);
@@ -212,7 +216,8 @@ LL |         let _val: Wrap<fn()> = mem::zeroed();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this struct field)
+   = note: `Wrap<fn()>` must be non-null
+note: because function pointers must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -227,7 +232,8 @@ LL |         let _val: Wrap<fn()> = mem::uninitialized();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this struct field)
+   = note: `Wrap<fn()>` must be non-null
+note: because function pointers must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -242,7 +248,8 @@ LL |         let _val: WrapEnum<fn()> = mem::zeroed();
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `WrapEnum<fn()>` must be non-null
+note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:18:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -257,7 +264,8 @@ LL |         let _val: WrapEnum<fn()> = mem::uninitialized();
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `WrapEnum<fn()>` must be non-null
+note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:18:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -272,7 +280,12 @@ LL |         let _val: Wrap<(RefPair, i32)> = mem::zeroed();
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+note: `RefPair` must be non-null (in this struct field)
+  --> $DIR/invalid_value.rs:17:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:15:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -287,7 +300,12 @@ LL |         let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+note: `RefPair` must be non-null (in this struct field)
+  --> $DIR/invalid_value.rs:17:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:15:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -314,6 +332,7 @@ LL |         let _val: NonNull<i32> = mem::uninitialized();
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::ptr::NonNull<i32>` must be non-null
+   = note: raw pointers must be initialized
 
 error: the type `(NonZeroU32, i32)` does not permit zero-initialization
   --> $DIR/invalid_value.rs:95:39
@@ -336,6 +355,7 @@ LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
    |                                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::num::NonZeroU32` must be non-null
+   = note: integers must be initialized
 
 error: the type `*const dyn Send` does not permit zero-initialization
   --> $DIR/invalid_value.rs:98:37
@@ -420,7 +440,8 @@ LL |         let _val: OneFruitNonZero = mem::zeroed();
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `OneFruitNonZero` must be non-null
+note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
@@ -435,11 +456,13 @@ LL |         let _val: OneFruitNonZero = mem::uninitialized();
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `OneFruitNonZero` must be non-null
+note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
    |            ^^^^^^^^^^
+   = note: integers must be initialized
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:112:26
@@ -461,6 +484,7 @@ LL |         let _val: Wrap<char> = mem::uninitialized();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+   = note: `Wrap<char>` must be initialized inside its custom valid range
 note: characters must be a valid Unicode codepoint (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
@@ -477,6 +501,11 @@ LL |         let _val: NonBig = mem::uninitialized();
    |                            help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `NonBig` must be initialized inside its custom valid range
+note: integers must be initialized (in this struct field)
+  --> $DIR/invalid_value.rs:23:26
+   |
+LL | pub(crate) struct NonBig(u64);
+   |                          ^^^
 
 error: the type `Fruit` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:121:27
@@ -513,7 +542,7 @@ LL |         let _val: i32 = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: integers must not be uninitialized
+   = note: integers must be initialized
 
 error: the type `f32` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:130:25
@@ -524,7 +553,7 @@ LL |         let _val: f32 = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: floats must not be uninitialized
+   = note: floats must be initialized
 
 error: the type `*const ()` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:133:31
@@ -535,7 +564,7 @@ LL |         let _val: *const () = mem::uninitialized();
    |                               this code causes undefined behavior when executed
    |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: raw pointers must not be uninitialized
+   = note: raw pointers must be initialized
 
 error: the type `*const [()]` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:136:33
@@ -546,7 +575,7 @@ LL |         let _val: *const [()] = mem::uninitialized();
    |                                 this code causes undefined behavior when executed
    |                                 help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: raw pointers must not be uninitialized
+   = note: raw pointers must be initialized
 
 error: the type `WrapAroundRange` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:139:37
@@ -558,6 +587,11 @@ LL |         let _val: WrapAroundRange = mem::uninitialized();
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `WrapAroundRange` must be initialized inside its custom valid range
+note: integers must be initialized (in this struct field)
+  --> $DIR/invalid_value.rs:49:35
+   |
+LL | pub(crate) struct WrapAroundRange(u8);
+   |                                   ^^
 
 error: the type `Result<i32, i32>` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:144:38
@@ -628,6 +662,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::ptr::NonNull<i32>` must be non-null
+   = note: raw pointers must be initialized
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:159:26
diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
index 835edb4b0ae..249b48ab194 100644
--- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr
@@ -13,8 +13,8 @@ LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
    |        ^^^^^ --  --
 help: add missing lifetime argument
    |
-LL |     S.early::<'static, 'b>();
-   |                      ++++
+LL |     S.early::<'static, 'static>();
+   |                      +++++++++
 
 error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
   --> $DIR/method-call-lifetime-args-fail.rs:18:7
@@ -213,8 +213,8 @@ LL |     fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
    |        ^^^^^ --  --
 help: add missing lifetime argument
    |
-LL |     S::early::<'static, 'b>(S);
-   |                       ++++
+LL |     S::early::<'static, 'static>(S);
+   |                       +++++++++
 
 error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
   --> $DIR/method-call-lifetime-args-fail.rs:65:8
diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr
index 45e16264973..dea7c4695cc 100644
--- a/src/test/ui/pattern/non-structural-match-types.stderr
+++ b/src/test/ui/pattern/non-structural-match-types.stderr
@@ -4,7 +4,7 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used
 LL |         const { || {} } => {},
    |         ^^^^^^^^^^^^^^^
 
-error: `impl Future<Output = ()>` cannot be used in patterns
+error: `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:12:9
    |
 LL |         const { async {} } => {},
diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 012bc848d4b..2a0e9497a21 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -119,7 +119,7 @@ hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
 hir-stats ----------------------------------------------------------------
 hir-stats ForeignItemRef            24 ( 0.3%)             1            24
-hir-stats Lifetime                  32 ( 0.3%)             1            32
+hir-stats Lifetime                  24 ( 0.3%)             1            24
 hir-stats Mod                       32 ( 0.3%)             1            32
 hir-stats ExprField                 40 ( 0.4%)             1            40
 hir-stats TraitItemRef              56 ( 0.6%)             2            28
@@ -152,7 +152,7 @@ hir-stats - Struct                    72 ( 0.8%)             1
 hir-stats - Binding                  216 ( 2.4%)             3
 hir-stats GenericParam             400 ( 4.4%)             5            80
 hir-stats Generics                 560 ( 6.1%)            10            56
-hir-stats Ty                       720 ( 7.8%)            15            48
+hir-stats Ty                       720 ( 7.9%)            15            48
 hir-stats - Ptr                       48 ( 0.5%)             1
 hir-stats - Rptr                      48 ( 0.5%)             1
 hir-stats - Path                     624 ( 6.8%)            13
@@ -171,8 +171,8 @@ hir-stats - ForeignMod                80 ( 0.9%)             1
 hir-stats - Impl                      80 ( 0.9%)             1
 hir-stats - Fn                       160 ( 1.7%)             2
 hir-stats - Use                      400 ( 4.4%)             5
-hir-stats Path                   1_280 (13.9%)            32            40
+hir-stats Path                   1_280 (14.0%)            32            40
 hir-stats PathSegment            1_920 (20.9%)            40            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  9_176
+hir-stats Total                  9_168
 hir-stats
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 918d37e6559..34ff59a9bb0 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -87,7 +87,7 @@ LL | |     }
    |       arguments to this function are incorrect
    |
    = note:     expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
-           found `async` block `impl Future<Output = {integer}>`
+           found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
index fe291e021bc..9839e973bdf 100644
--- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
@@ -2,20 +2,62 @@
 // gate-test-anonymous_lifetime_in_impl_trait
 // Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.
 
-fn f(_: impl Iterator<Item = &'_ ()>) {}
-//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+mod elided {
+    fn f(_: impl Iterator<Item = &()>) {}
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
 
-fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
-//~| ERROR missing lifetime specifier
+    fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+    //~| ERROR missing lifetime specifier
 
-// Anonymous lifetimes in async fn are already allowed.
-// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
-async fn h(_: impl Iterator<Item = &'_ ()>) {}
+    // Anonymous lifetimes in async fn are already allowed.
+    // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+    async fn h(_: impl Iterator<Item = &()>) {}
 
-// Anonymous lifetimes in async fn are already allowed.
-// But that lifetime does not participate in resolution.
-async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-//~^ ERROR missing lifetime specifier
+    // Anonymous lifetimes in async fn are already allowed.
+    // But that lifetime does not participate in resolution.
+    async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+    //~^ ERROR missing lifetime specifier
+}
+
+mod underscore {
+    fn f(_: impl Iterator<Item = &'_ ()>) {}
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+    fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+    //~| ERROR missing lifetime specifier
+
+    // Anonymous lifetimes in async fn are already allowed.
+    // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
+    async fn h(_: impl Iterator<Item = &'_ ()>) {}
+
+    // Anonymous lifetimes in async fn are already allowed.
+    // But that lifetime does not participate in resolution.
+    async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+    //~^ ERROR missing lifetime specifier
+}
+
+mod alone_in_path {
+    trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; }
+
+    fn f(_: impl Foo) {}
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+    fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+    //~| ERROR missing lifetime specifier
+}
+
+mod in_path {
+    trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; }
+
+    fn f(_: impl Foo<()>) {}
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+
+    fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+    //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
+    //~| ERROR missing lifetime specifier
+}
 
 fn main() {}
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
index 9833da13ffc..50806a67255 100644
--- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -1,52 +1,172 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:8:50
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:9:54
    |
-LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |                                                  ^^ expected named lifetime parameter
+LL |     fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+   |                                                      ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
 help: consider using the `'static` lifetime
    |
-LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
-   |                                                  ~~~~~~~
+LL |     fn g(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
+   |                                                       +++++++
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:18:56
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:19:60
    |
-LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |                                                        ^^ expected named lifetime parameter
+LL |     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+   |                                                            ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
 help: consider using the `'static` lifetime
    |
-LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
-   |                                                        ~~~~~~~
+LL |     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
+   |                                                             +++++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58
+   |
+LL |     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+   |                                                          ^^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+   |                                                          ~~~~~~~
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
+   |
+LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+   |                                                                ^^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
+   |                                                                ~~~~~~~
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
+   |
+LL |     fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+   |                                     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() }
+   |                                      +++++++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:58:41
+   |
+LL |     fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+   |                                         ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL |     fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() }
+   |                                          +++++++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35
+   |
+LL |     fn f(_: impl Iterator<Item = &()>) {}
+   |                                   ^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
+   |         ++++                          ++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:9:39
+   |
+LL |     fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+   |                                       ^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&()> { x.next() }
+   |         ++++                              ++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:24:35
+   |
+LL |     fn f(_: impl Iterator<Item = &'_ ()>) {}
+   |                                   ^^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
+   |         ++++                          ~~
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:27:39
+   |
+LL |     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+   |                                       ^^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'_ ()> { x.next() }
+   |         ++++                              ~~
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:44:18
+   |
+LL |     fn f(_: impl Foo) {}
+   |                  ^^^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn f<'a>(_: impl Foo<'a>) {}
+   |         ++++            ++++
+
+error[E0658]: anonymous lifetimes in `impl Trait` are unstable
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:47:22
+   |
+LL |     fn g(mut x: impl Foo) -> Option<&()> { x.next() }
+   |                      ^^^ expected named lifetime parameter
+   |
+   = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
+   |         ++++                ++++
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
    |
-LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
-   |                               ^^ expected named lifetime parameter
+LL |     fn f(_: impl Foo<()>) {}
+   |                      ^ expected named lifetime parameter
    |
    = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
 help: consider introducing a named lifetime parameter
    |
-LL | fn f<'a>(_: impl Iterator<Item = &'_'a  ()>) {}
-   |     ++++                            ++
+LL |     fn f<'a>(_: impl Foo<'a, ()>) {}
+   |         ++++             +++
 
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:8:31
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
    |
-LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |                               ^^ expected named lifetime parameter
+LL |     fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
+   |                          ^ expected named lifetime parameter
    |
    = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
 help: consider introducing a named lifetime parameter
    |
-LL | fn g<'a>(x: impl Iterator<Item = &'_'a  ()>) -> Option<&'_ ()> { x.next() }
-   |     ++++                            ++
+LL |     fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
+   |         ++++                 +++
 
-error: aborting due to 4 previous errors
+error: aborting due to 14 previous errors
 
 Some errors have detailed explanations: E0106, E0658.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
index 10fb28c1891..997bbb5e9b5 100644
--- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr
@@ -166,8 +166,8 @@ LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                       ++++
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       +++++++++
 
 error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:39:44
@@ -184,8 +184,8 @@ LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                       ++++
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       +++++++++
 
 error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:39:44
@@ -202,8 +202,8 @@ LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                       ++++
+LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                       +++++++++
 
 error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:39:44
@@ -256,8 +256,8 @@ LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                        ++++
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        +++++++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:47:45
@@ -274,8 +274,8 @@ LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                        ++++
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        +++++++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:47:45
@@ -292,8 +292,8 @@ LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
 help: add missing lifetime argument
    |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
-   |                                                        ++++
+LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
+   |                                                        +++++++++
 
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/missing-lifetime-specifier.rs:47:45
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 0bb9eca1528..220941dcd5d 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -10,8 +10,8 @@ use rustc_hir::lang_items;
 use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
     BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
-    ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
-    TraitItemKind, Ty, TyKind, WherePredicate,
+    ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
+    TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter as middle_nested_filter;
@@ -180,7 +180,7 @@ fn check_fn_inner<'tcx>(
                             _ => None,
                         });
                         for bound in lifetimes {
-                            if bound.name != LifetimeName::Static && !bound.is_elided() {
+                            if !bound.is_static() && !bound.is_elided() {
                                 return;
                             }
                         }
@@ -414,17 +414,13 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
 
     fn record(&mut self, lifetime: &Option<Lifetime>) {
         if let Some(ref lt) = *lifetime {
-            if lt.name == LifetimeName::Static {
+            if lt.is_static() {
                 self.lts.push(RefLt::Static);
-            } else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
+            } else if lt.is_anonymous() {
                 // Fresh lifetimes generated should be ignored.
                 self.lts.push(RefLt::Unnamed);
-            } else if lt.is_elided() {
-                self.lts.push(RefLt::Unnamed);
-            } else if let LifetimeName::Param(def_id, _) = lt.name {
+            } else if let LifetimeName::Param(def_id) = lt.res {
                 self.lts.push(RefLt::Named(def_id));
-            } else {
-                self.lts.push(RefLt::Unnamed);
             }
         } else {
             self.lts.push(RefLt::Unnamed);
@@ -472,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
                 walk_item(self, item);
                 self.lts.truncate(len);
                 self.lts.extend(bounds.iter().filter_map(|bound| match bound {
-                    GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id, _) = l.name {
+                    GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
                         RefLt::Named(def_id)
                     } else {
                         RefLt::Unnamed
@@ -498,10 +494,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
     }
 
     fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
-        if let GenericArg::Lifetime(l) = generic_arg
-            && let LifetimeName::Param(def_id, _) = l.name
-        {
-            self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
+        if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
+            self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
         }
         // Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands.
         // walk_generic_arg(self, generic_arg);
@@ -577,7 +571,7 @@ where
 
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
-        self.map.remove(&lifetime.name.ident().name);
+        self.map.remove(&lifetime.ident.name);
     }
 
     fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
@@ -601,7 +595,9 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
         .params
         .iter()
         .filter_map(|par| match par.kind {
-            GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
+            GenericParamKind::Lifetime {
+                kind: LifetimeParamKind::Explicit,
+            } => Some((par.name.ident().name, par.span)),
             _ => None,
         })
         .collect();
@@ -626,7 +622,9 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
         .params
         .iter()
         .filter_map(|par| match par.kind {
-            GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
+            GenericParamKind::Lifetime {
+                kind: LifetimeParamKind::Explicit,
+            } => Some((par.name.ident().name, par.span)),
             _ => None,
         })
         .collect();
@@ -653,7 +651,7 @@ struct BodyLifetimeChecker {
 impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
-        if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.ident().name != kw::StaticLifetime {
+        if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
             self.lifetimes_used_in_body = true;
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 6a98df49912..075ecbe7ede 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -118,7 +118,7 @@ fn future_trait_ref<'tcx>(
                 .iter()
                 .filter_map(|bound| {
                     if let GenericArg::Lifetime(lt) = bound {
-                        Some(lt.name)
+                        Some(lt.res)
                     } else {
                         None
                     }
@@ -153,7 +153,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
         .iter()
         .filter_map(|ty| {
             if let TyKind::Rptr(lt, _) = ty.kind {
-                Some(lt.name)
+                Some(lt.res)
             } else {
                 None
             }
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index d28e97b7943..92920bbad6e 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -12,8 +12,8 @@ use rustc_hir::hir_id::HirIdMap;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
     self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
-    ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn,
-    TraitItem, TraitItemKind, TyKind, Unsafety,
+    ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind,
+    TyKind, Unsafety,
 };
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{Obligation, ObligationCause};
@@ -343,21 +343,16 @@ impl PtrArg<'_> {
 }
 
 struct RefPrefix {
-    lt: LifetimeName,
+    lt: Lifetime,
     mutability: Mutability,
 }
 impl fmt::Display for RefPrefix {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use fmt::Write;
         f.write_char('&')?;
-        match self.lt {
-            LifetimeName::Param(_, ParamName::Plain(name)) => {
-                name.fmt(f)?;
-                f.write_char(' ')?;
-            },
-            LifetimeName::Infer => f.write_str("'_ ")?,
-            LifetimeName::Static => f.write_str("'static ")?,
-            _ => (),
+        if !self.lt.is_anonymous() {
+            self.lt.ident.fmt(f)?;
+            f.write_char(' ')?;
         }
         f.write_str(self.mutability.prefix_str())
     }
@@ -495,7 +490,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                         ty_name: name.ident.name,
                         method_renames,
                         ref_prefix: RefPrefix {
-                            lt: lt.name,
+                            lt: lt.clone(),
                             mutability,
                         },
                         deref_ty,
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 9c662995840..65dfe7637ea 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -31,10 +31,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
                         return false;
                     }
 
-                    let ltopt = if lt.name.is_anonymous() {
+                    let ltopt = if lt.is_anonymous() {
                         String::new()
                     } else {
-                        format!("{} ", lt.name.ident().as_str())
+                        format!("{} ", lt.ident.as_str())
                     };
 
                     if mut_ty.mutbl == Mutability::Mut {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index c944fc51e82..07fb6af91ba 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -7,7 +7,7 @@ use rustc_hir::def::Res;
 use rustc_hir::HirIdMap;
 use rustc_hir::{
     ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
-    GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
+    GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
     PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lexer::{tokenize, TokenKind};
@@ -337,7 +337,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
-        left.name == right.name
+        left.res == right.res
     }
 
     fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
@@ -925,16 +925,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     }
 
     pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
-        std::mem::discriminant(&lifetime.name).hash(&mut self.s);
-        if let LifetimeName::Param(param_id, ref name) = lifetime.name {
-            std::mem::discriminant(name).hash(&mut self.s);
+        lifetime.ident.name.hash(&mut self.s);
+        std::mem::discriminant(&lifetime.res).hash(&mut self.s);
+        if let LifetimeName::Param(param_id) = lifetime.res {
             param_id.hash(&mut self.s);
-            match name {
-                ParamName::Plain(ref ident) => {
-                    ident.name.hash(&mut self.s);
-                },
-                ParamName::Fresh | ParamName::Error => {},
-            }
         }
     }
 
diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs
index 95ea8866609..70e7440f730 100644
--- a/src/tools/jsondoclint/src/json_find.rs
+++ b/src/tools/jsondoclint/src/json_find.rs
@@ -2,7 +2,7 @@ use std::fmt::Write;
 
 use serde_json::Value;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub enum SelectorPart {
     Field(String),
     Index(usize),
@@ -72,3 +72,6 @@ fn find_selector_recursive(
         }
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/src/tools/jsondoclint/src/json_find/tests.rs b/src/tools/jsondoclint/src/json_find/tests.rs
new file mode 100644
index 00000000000..2a533530714
--- /dev/null
+++ b/src/tools/jsondoclint/src/json_find/tests.rs
@@ -0,0 +1,27 @@
+use super::*;
+
+#[test]
+fn basic_find() {
+    use SelectorPart::*;
+
+    let j = serde_json::json!({
+        "index": {
+            "4": {
+                "inner": {
+                    "items": ["1", "2", "3"]
+                }
+            }
+        }
+    });
+
+    let sel = find_selector(&j, &serde_json::json!("1"));
+    let exp: Vec<Vec<SelectorPart>> = vec![vec![
+        Field("index".to_owned()),
+        Field("4".to_owned()),
+        Field("inner".to_owned()),
+        Field("items".to_owned()),
+        Index(0),
+    ]];
+
+    assert_eq!(exp, sel);
+}
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index 70d7a82a576..fc54c421b4b 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -9,13 +9,13 @@ pub(crate) mod item_kind;
 mod json_find;
 mod validator;
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 struct Error {
     kind: ErrorKind,
     id: Id,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 enum ErrorKind {
     NotFound,
     Custom(String),
diff --git a/triagebot.toml b/triagebot.toml
index 985e065652d..133fbaede21 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -15,7 +15,7 @@ allow-unauthenticated = [
     "llvm-main",
     "needs-fcp",
     "relnotes",
-    "requires-nightly",
+    "requires-*",
     "regression-*",
     "perf-*",
     "AsyncAwait-OnDeck",
@@ -334,6 +334,13 @@ cc = ["@rust-lang/wg-mir-opt"]
 message = "Some changes occurred in const_evaluatable.rs"
 cc = ["@lcnr"]
 
+[mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
+message = """
+Some changes occurred in engine.rs, potentially modifying the public API \
+of `ObligationCtxt`.
+"""
+cc = ["@lcnr"]
+
 [mentions."compiler/rustc_error_codes/src/error_codes.rs"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]