about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs3
-rw-r--r--compiler/rustc_hir/src/def.rs9
-rw-r--r--compiler/rustc_hir/src/hir.rs21
-rw-r--r--compiler/rustc_hir/src/intravisit.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs31
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs1
-rw-r--r--compiler/rustc_resolve/src/late.rs239
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs568
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs8
-rw-r--r--compiler/rustc_typeck/src/collect.rs12
-rw-r--r--src/test/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs2
15 files changed, 202 insertions, 747 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d4b41aad08c..a1bf0f94964 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1883,29 +1883,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
                 hir::LifetimeName::Param(param, ParamName::Fresh)
             }
-            LifetimeRes::Anonymous { binder, elided } => {
-                let mut l_name = None;
-                if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
-                    if !captured_lifetimes.binders_to_ignore.contains(&binder) {
-                        let p_id = self.next_node_id();
-                        let p_def_id = self.create_def(
-                            captured_lifetimes.parent_def_id,
-                            p_id,
-                            DefPathData::LifetimeNs(kw::UnderscoreLifetime),
-                        );
-                        captured_lifetimes
-                            .captures
-                            .insert(p_def_id, (span, p_id, ParamName::Fresh, res));
-                        l_name = Some(hir::LifetimeName::Param(p_def_id, ParamName::Fresh));
-                    }
-                    self.captured_lifetimes = Some(captured_lifetimes);
-                };
-                l_name.unwrap_or(if elided {
-                    hir::LifetimeName::Implicit
-                } else {
-                    hir::LifetimeName::Underscore
-                })
-            }
+            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),
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 4cf1ac4d7ab..0662d4d882f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -589,8 +589,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
             hir::LifetimeName::Param(_, hir::ParamName::Fresh)
             | hir::LifetimeName::ImplicitObjectLifetimeDefault
-            | hir::LifetimeName::Implicit
-            | hir::LifetimeName::Underscore => {
+            | hir::LifetimeName::Infer => {
                 // In this case, the user left off the lifetime; so
                 // they wrote something like:
                 //
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index c0d5d2bc46d..be5b7eccbaf 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -738,13 +738,8 @@ pub enum LifetimeRes {
         binder: NodeId,
     },
     /// This variant is used for anonymous lifetimes that we did not resolve during
-    /// late resolution.  Shifting the work to the HIR lifetime resolver.
-    Anonymous {
-        /// Id of the introducing place. See `Param`.
-        binder: NodeId,
-        /// Whether this lifetime was spelled or elided.
-        elided: bool,
-    },
+    /// late resolution.  Those lifetimes will be inferred by typechecking.
+    Infer,
     /// Explicit `'static` lifetime.
     Static,
     /// Resolution failure.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 18ffc227fed..f71400898e6 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -90,9 +90,6 @@ pub enum LifetimeName {
     /// User-given names or fresh (synthetic) names.
     Param(LocalDefId, ParamName),
 
-    /// User wrote nothing (e.g., the lifetime in `&u32`).
-    Implicit,
-
     /// Implicit lifetime in a context like `dyn Foo`. This is
     /// distinguished from implicit lifetimes elsewhere because the
     /// lifetime that they default to must appear elsewhere within the
@@ -110,8 +107,9 @@ pub enum LifetimeName {
     /// that was already reported.
     Error,
 
-    /// User wrote specifies `'_`.
-    Underscore,
+    /// User wrote an anonymous lifetime, either `'_` or nothing.
+    /// The semantics of this lifetime should be inferred by typechecking code.
+    Infer,
 
     /// User wrote `'static`.
     Static,
@@ -120,10 +118,8 @@ pub enum LifetimeName {
 impl LifetimeName {
     pub fn ident(&self) -> Ident {
         match *self {
-            LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit
-            | LifetimeName::Error => Ident::empty(),
-            LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
+            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(),
         }
@@ -132,8 +128,7 @@ impl LifetimeName {
     pub fn is_anonymous(&self) -> bool {
         match *self {
             LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit
-            | LifetimeName::Underscore
+            | LifetimeName::Infer
             | LifetimeName::Param(_, ParamName::Fresh)
             | LifetimeName::Error => true,
             LifetimeName::Static | LifetimeName::Param(..) => false,
@@ -142,9 +137,7 @@ impl LifetimeName {
 
     pub fn is_elided(&self) -> bool {
         match self {
-            LifetimeName::ImplicitObjectLifetimeDefault
-            | LifetimeName::Implicit
-            | LifetimeName::Underscore => true,
+            LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
 
             // It might seem surprising that `Fresh` counts as
             // *not* elided -- but this is because, as far as the code
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index d00b65da7e6..640974115b9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -496,9 +496,8 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
         | LifetimeName::Param(_, ParamName::Error)
         | LifetimeName::Static
         | LifetimeName::Error
-        | LifetimeName::Implicit
         | LifetimeName::ImplicitObjectLifetimeDefault
-        | LifetimeName::Underscore => {}
+        | LifetimeName::Infer => {}
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index e5ae835e813..c1b201da691 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -100,23 +100,6 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                 // the lifetime of the TyRptr
                 let hir_id = lifetime.hir_id;
                 match (self.tcx.named_region(hir_id), self.bound_region) {
-                    // Find the index of the anonymous region that was part of the
-                    // error. We will then search the function parameters for a bound
-                    // region at the right depth with the same index
-                    (
-                        Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)),
-                        ty::BrAnon(br_index),
-                    ) => {
-                        debug!(
-                            "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
-                            debruijn_index, anon_index, br_index
-                        );
-                        if debruijn_index == self.current_index && anon_index == br_index {
-                            self.found_type = Some(arg);
-                            return; // we can stop visiting now
-                        }
-                    }
-
                     // Find the index of the named region that was part of the
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
@@ -151,8 +134,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                             rl::Region::Static
                             | rl::Region::Free(_, _)
                             | rl::Region::EarlyBound(_, _)
-                            | rl::Region::LateBound(_, _, _)
-                            | rl::Region::LateBoundAnon(_, _, _),
+                            | rl::Region::LateBound(_, _, _),
                         )
                         | None,
                         _,
@@ -206,16 +188,6 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
         match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
             // the lifetime of the TyPath!
-            (
-                Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)),
-                ty::BrAnon(br_index),
-            ) => {
-                if debruijn_index == self.current_index && anon_index == br_index {
-                    self.found_it = true;
-                    return;
-                }
-            }
-
             (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
                 debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                 if id == def_id {
@@ -239,7 +211,6 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
                     rl::Region::Static
                     | rl::Region::EarlyBound(_, _)
                     | rl::Region::LateBound(_, _, _)
-                    | rl::Region::LateBoundAnon(_, _, _)
                     | rl::Region::Free(_, _),
                 )
                 | None,
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index c71ba7b1753..9b2f4456705 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -12,7 +12,6 @@ pub enum Region {
     Static,
     EarlyBound(/* index */ u32, /* lifetime decl */ DefId),
     LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
-    LateBoundAnon(ty::DebruijnIndex, /* late-bound index */ u32, /* anon index */ u32),
     Free(DefId, /* lifetime decl */ DefId),
 }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9b5fd4ea6d1..ed65100ae77 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -262,9 +262,6 @@ enum LifetimeRibKind {
     /// error on default object bounds (e.g., `Box<dyn Foo>`).
     AnonymousReportError,
 
-    /// Pass responsibility to `resolve_lifetime` code for all cases.
-    AnonymousPassThrough(NodeId),
-
     /// Replace all anonymous lifetimes by provided lifetime.
     Elided(LifetimeRes),
 
@@ -698,14 +695,25 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     },
                     |this| {
                         this.visit_generic_params(&bare_fn.generic_params, false);
-                        this.resolve_fn_signature(
-                            ty.id,
-                            None,
-                            false,
-                            // We don't need to deal with patterns in parameters, because
-                            // they are not possible for foreign or bodiless functions.
-                            bare_fn.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
-                            &bare_fn.decl.output,
+                        this.with_lifetime_rib(
+                            LifetimeRibKind::AnonymousCreateParameter {
+                                binder: ty.id,
+                                report_in_path: false,
+                            },
+                            |this| {
+                                this.resolve_fn_signature(
+                                    ty.id,
+                                    false,
+                                    // We don't need to deal with patterns in parameters, because
+                                    // they are not possible for foreign or bodiless functions.
+                                    bare_fn
+                                        .decl
+                                        .inputs
+                                        .iter()
+                                        .map(|Param { ty, .. }| (None, &**ty)),
+                                    &bare_fn.decl.output,
+                                )
+                            },
                         );
                     },
                 )
@@ -785,12 +793,19 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
             | FnKind::Fn(_, _, sig, _, generics, None) => {
                 self.visit_fn_header(&sig.header);
                 self.visit_generics(generics);
-                self.resolve_fn_signature(
-                    fn_id,
-                    None,
-                    sig.decl.has_self(),
-                    sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
-                    &sig.decl.output,
+                self.with_lifetime_rib(
+                    LifetimeRibKind::AnonymousCreateParameter {
+                        binder: fn_id,
+                        report_in_path: false,
+                    },
+                    |this| {
+                        this.resolve_fn_signature(
+                            fn_id,
+                            sig.decl.has_self(),
+                            sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
+                            &sig.decl.output,
+                        )
+                    },
                 );
                 return;
             }
@@ -815,15 +830,22 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         let declaration = &sig.decl;
                         let async_node_id = sig.header.asyncness.opt_return_id();
 
-                        this.resolve_fn_signature(
-                            fn_id,
-                            async_node_id,
-                            declaration.has_self(),
-                            declaration
-                                .inputs
-                                .iter()
-                                .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
-                            &declaration.output,
+                        this.with_lifetime_rib(
+                            LifetimeRibKind::AnonymousCreateParameter {
+                                binder: fn_id,
+                                report_in_path: async_node_id.is_some(),
+                            },
+                            |this| {
+                                this.resolve_fn_signature(
+                                    fn_id,
+                                    declaration.has_self(),
+                                    declaration
+                                        .inputs
+                                        .iter()
+                                        .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
+                                    &declaration.output,
+                                )
+                            },
                         );
 
                         // Construct the list of in-scope lifetime parameters for async lowering.
@@ -868,7 +890,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                             let previous_state = replace(&mut this.in_func_body, true);
                             // Resolve the function body, potentially inside the body of an async closure
                             this.with_lifetime_rib(
-                                LifetimeRibKind::AnonymousPassThrough(fn_id),
+                                LifetimeRibKind::Elided(LifetimeRes::Infer),
                                 |this| this.visit_block(body),
                             );
 
@@ -896,7 +918,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         this.with_lifetime_rib(
                             match binder {
                                 ClosureBinder::NotPresent => {
-                                    LifetimeRibKind::AnonymousPassThrough(fn_id)
+                                    LifetimeRibKind::Elided(LifetimeRes::Infer)
                                 }
                                 ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
                             },
@@ -908,7 +930,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         let previous_state = replace(&mut this.in_func_body, true);
                         // Resolve the function body, potentially inside the body of an async closure
                         this.with_lifetime_rib(
-                            LifetimeRibKind::AnonymousPassThrough(fn_id),
+                            LifetimeRibKind::Elided(LifetimeRes::Infer),
                             |this| this.visit_expr(body),
                         );
 
@@ -1038,12 +1060,19 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                                 kind: LifetimeBinderKind::PolyTrait,
                                 ..
                             } => {
-                                self.resolve_fn_signature(
-                                    binder,
-                                    None,
-                                    false,
-                                    p_args.inputs.iter().map(|ty| (None, &**ty)),
-                                    &p_args.output,
+                                self.with_lifetime_rib(
+                                    LifetimeRibKind::AnonymousCreateParameter {
+                                        binder,
+                                        report_in_path: false,
+                                    },
+                                    |this| {
+                                        this.resolve_fn_signature(
+                                            binder,
+                                            false,
+                                            p_args.inputs.iter().map(|ty| (None, &**ty)),
+                                            &p_args.output,
+                                        )
+                                    },
                                 );
                                 break;
                             }
@@ -1053,8 +1082,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                                 visit::walk_generic_args(self, path_span, args);
                                 break;
                             }
-                            LifetimeRibKind::AnonymousPassThrough(..)
-                            | LifetimeRibKind::AnonymousCreateParameter { .. }
+                            LifetimeRibKind::AnonymousCreateParameter { .. }
                             | LifetimeRibKind::AnonymousReportError
                             | LifetimeRibKind::Elided(_)
                             | LifetimeRibKind::ElisionFailure
@@ -1415,8 +1443,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                     | LifetimeRibKind::AnonymousReportError
                                     | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
                                     // An anonymous lifetime is legal here, go ahead.
-                                    LifetimeRibKind::AnonymousPassThrough(_)
-                                    | LifetimeRibKind::AnonymousCreateParameter { .. } => {
+                                    LifetimeRibKind::AnonymousCreateParameter { .. } => {
                                         Some(LifetimeUseSet::One { use_span: ident.span, use_ctxt })
                                     }
                                     // Only report if eliding the lifetime would have the same
@@ -1527,14 +1554,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
                     return;
                 }
-                LifetimeRibKind::AnonymousPassThrough(node_id) => {
-                    self.record_lifetime_res(
-                        lifetime.id,
-                        LifetimeRes::Anonymous { binder: node_id, elided },
-                        elision_candidate,
-                    );
-                    return;
-                }
                 LifetimeRibKind::Elided(res) => {
                     self.record_lifetime_res(lifetime.id, res, elision_candidate);
                     return;
@@ -1632,6 +1651,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | PathSource::Struct
                 | PathSource::TupleStruct(..) => false,
             };
+            if !missing && !segment.has_generic_args {
+                continue;
+            }
 
             let elided_lifetime_span = if segment.has_generic_args {
                 // If there are brackets, but not generic arguments, then use the opening bracket
@@ -1653,37 +1675,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
             if !missing {
                 // Do not create a parameter for patterns and expressions.
-                for rib in self.lifetime_ribs.iter().rev() {
-                    match rib.kind {
-                        LifetimeRibKind::AnonymousPassThrough(binder) => {
-                            let res = LifetimeRes::Anonymous { binder, elided: true };
-                            for id in node_ids {
-                                self.record_lifetime_res(id, res, LifetimeElisionCandidate::Named);
-                            }
-                            break;
-                        }
-                        // `LifetimeRes::Error`, which would usually be used in the case of
-                        // `ReportError`, is unsuitable here, as we don't emit an error yet.  Instead,
-                        // we simply resolve to an implicit lifetime, which will be checked later, at
-                        // which point a suitable error will be emitted.
-                        LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
-                            // FIXME(cjgillot) This resolution is wrong, but this does not matter
-                            // since these cases are erroneous anyway.  Lifetime resolution should
-                            // emit a "missing lifetime specifier" diagnostic.
-                            let res =
-                                LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
-                            for id in node_ids {
-                                self.record_lifetime_res(id, res, LifetimeElisionCandidate::Named);
-                            }
-                            break;
-                        }
-                        LifetimeRibKind::AnonymousCreateParameter { .. }
-                        | LifetimeRibKind::Elided(_)
-                        | LifetimeRibKind::ElisionFailure
-                        | LifetimeRibKind::Generics { .. }
-                        | LifetimeRibKind::ConstGeneric
-                        | LifetimeRibKind::AnonConst => {}
-                    }
+                for id in node_ids {
+                    self.record_lifetime_res(
+                        id,
+                        LifetimeRes::Infer,
+                        LifetimeElisionCandidate::Named,
+                    );
                 }
                 continue;
             }
@@ -1750,19 +1747,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                         }
                         break;
                     }
-                    // `PassThrough` is the normal case.
-                    LifetimeRibKind::AnonymousPassThrough(binder) => {
-                        let res = LifetimeRes::Anonymous { binder, elided: true };
-                        let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
-                        for id in node_ids {
-                            self.record_lifetime_res(
-                                id,
-                                res,
-                                replace(&mut candidate, LifetimeElisionCandidate::Ignore),
-                            );
-                        }
-                        break;
-                    }
                     LifetimeRibKind::Elided(res) => {
                         let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
                         for id in node_ids {
@@ -1837,15 +1821,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             )
         }
         match res {
-            LifetimeRes::Param { .. }
-            | LifetimeRes::Fresh { .. }
-            | LifetimeRes::Anonymous { .. }
-            | LifetimeRes::Static => {
+            LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => {
                 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
                     candidates.insert(res, candidate);
                 }
             }
-            LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
+            LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
         }
     }
 
@@ -1864,18 +1845,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
     fn resolve_fn_signature(
         &mut self,
         fn_id: NodeId,
-        async_node_id: Option<NodeId>,
         has_self: bool,
         inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
         output_ty: &'ast FnRetTy,
     ) {
         // Add each argument to the rib.
-        let parameter_rib = LifetimeRibKind::AnonymousCreateParameter {
-            binder: fn_id,
-            report_in_path: async_node_id.is_some(),
-        };
-        let elision_lifetime =
-            self.with_lifetime_rib(parameter_rib, |this| this.resolve_fn_params(has_self, inputs));
+        let elision_lifetime = self.resolve_fn_params(has_self, inputs);
         debug!(?elision_lifetime);
 
         let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
@@ -2268,26 +2243,23 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
                         this.visit_ty(ty);
                     });
-                    this.with_lifetime_rib(
-                        LifetimeRibKind::AnonymousPassThrough(item.id),
-                        |this| {
-                            if let Some(expr) = expr {
-                                let constant_item_kind = match item.kind {
-                                    ItemKind::Const(..) => ConstantItemKind::Const,
-                                    ItemKind::Static(..) => ConstantItemKind::Static,
-                                    _ => unreachable!(),
-                                };
-                                // We already forbid generic params because of the above item rib,
-                                // so it doesn't matter whether this is a trivial constant.
-                                this.with_constant_rib(
-                                    IsRepeatExpr::No,
-                                    HasGenericParams::Yes,
-                                    Some((item.ident, constant_item_kind)),
-                                    |this| this.visit_expr(expr),
-                                );
-                            }
-                        },
-                    );
+                    this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+                        if let Some(expr) = expr {
+                            let constant_item_kind = match item.kind {
+                                ItemKind::Const(..) => ConstantItemKind::Const,
+                                ItemKind::Static(..) => ConstantItemKind::Static,
+                                _ => unreachable!(),
+                            };
+                            // We already forbid generic params because of the above item rib,
+                            // so it doesn't matter whether this is a trivial constant.
+                            this.with_constant_rib(
+                                IsRepeatExpr::No,
+                                HasGenericParams::Yes,
+                                Some((item.ident, constant_item_kind)),
+                                |this| this.visit_expr(expr),
+                            );
+                        }
+                    });
                 });
             }
 
@@ -2544,7 +2516,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                         // Type parameters can already be used and as associated consts are
                         // not used as part of the type system, this is far less surprising.
                         self.with_lifetime_rib(
-                            LifetimeRibKind::AnonymousPassThrough(item.id),
+                            LifetimeRibKind::Elided(LifetimeRes::Infer),
                             |this| {
                                 this.with_constant_rib(
                                     IsRepeatExpr::No,
@@ -2717,17 +2689,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                     //
                     // Type parameters can already be used and as associated consts are
                     // not used as part of the type system, this is far less surprising.
-                    self.with_lifetime_rib(
-                        LifetimeRibKind::AnonymousPassThrough(item.id),
-                        |this| {
-                            this.with_constant_rib(
-                                IsRepeatExpr::No,
-                                HasGenericParams::Yes,
-                                None,
-                                |this| this.visit_expr(expr),
-                            )
-                        },
-                    );
+                    self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+                        this.with_constant_rib(
+                            IsRepeatExpr::No,
+                            HasGenericParams::Yes,
+                            None,
+                            |this| this.visit_expr(expr),
+                        )
+                    });
                 }
             }
             AssocItemKind::Fn(box Fn { generics, .. }) => {
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index a7fd7c427c7..94460e33d8b 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-filelength
 //! Resolution of early vs late bound lifetimes.
 //!
 //! Name resolution for lifetimes is performed on the AST and embedded into HIR.  From this
@@ -21,10 +20,9 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_lifetime::*;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_span::def_id::DefId;
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use std::borrow::Cow;
-use std::cell::Cell;
 use std::fmt;
 use std::mem::take;
 
@@ -33,8 +31,6 @@ trait RegionExt {
 
     fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
 
-    fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region;
-
     fn id(&self) -> Option<DefId>;
 
     fn shifted(self, amount: u32) -> Region;
@@ -65,16 +61,9 @@ impl RegionExt for Region {
         (def_id, Region::LateBound(depth, idx, def_id.to_def_id()))
     }
 
-    fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region {
-        let i = index.get();
-        index.set(i + 1);
-        let depth = ty::INNERMOST;
-        Region::LateBoundAnon(depth, named_late_bound_vars + i, i)
-    }
-
     fn id(&self) -> Option<DefId> {
         match *self {
-            Region::Static | Region::LateBoundAnon(..) => None,
+            Region::Static => None,
 
             Region::EarlyBound(_, id) | Region::LateBound(_, _, id) | Region::Free(_, id) => {
                 Some(id)
@@ -87,9 +76,6 @@ impl RegionExt for Region {
             Region::LateBound(debruijn, idx, id) => {
                 Region::LateBound(debruijn.shifted_in(amount), idx, id)
             }
-            Region::LateBoundAnon(debruijn, index, anon_index) => {
-                Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index)
-            }
             _ => self,
         }
     }
@@ -99,9 +85,6 @@ impl RegionExt for Region {
             Region::LateBound(debruijn, index, id) => {
                 Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id)
             }
-            Region::LateBoundAnon(debruijn, index, anon_index) => {
-                Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index)
-            }
             _ => self,
         }
     }
@@ -193,10 +176,6 @@ enum Scope<'a> {
 
         s: ScopeRef<'a>,
 
-        /// In some cases not allowing late bounds allows us to avoid ICEs.
-        /// This is almost ways set to true.
-        allow_late_bound: bool,
-
         /// If this binder comes from a where clause, specify how it was created.
         /// This is used to diagnose inaccessible lifetimes in APIT:
         /// ```ignore (illustrative)
@@ -215,9 +194,8 @@ enum Scope<'a> {
     },
 
     /// A scope which either determines unspecified lifetimes or errors
-    /// on them (e.g., due to ambiguity). For more details, see `Elide`.
+    /// on them (e.g., due to ambiguity).
     Elision {
-        elide: Elide,
         s: ScopeRef<'a>,
     },
 
@@ -273,7 +251,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 opaque_type_parent,
                 scope_type,
                 hir_id,
-                allow_late_bound,
                 where_bound_origin,
                 s: _,
             } => f
@@ -283,16 +260,13 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("opaque_type_parent", opaque_type_parent)
                 .field("scope_type", scope_type)
                 .field("hir_id", hir_id)
-                .field("allow_late_bound", allow_late_bound)
                 .field("where_bound_origin", where_bound_origin)
                 .field("s", &"..")
                 .finish(),
             Scope::Body { id, s: _ } => {
                 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
             }
-            Scope::Elision { elide, s: _ } => {
-                f.debug_struct("Elision").field("elide", elide).field("s", &"..").finish()
-            }
+            Scope::Elision { s: _ } => f.debug_struct("Elision").field("s", &"..").finish(),
             Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
                 .debug_struct("ObjectLifetimeDefault")
                 .field("lifetime", lifetime)
@@ -309,21 +283,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
     }
 }
 
-#[derive(Clone, Debug)]
-enum Elide {
-    /// Use a fresh anonymous late-bound lifetime each time, by
-    /// incrementing the counter to generate sequential indices. All
-    /// anonymous lifetimes must start *after* named bound vars.
-    FreshLateAnon(u32, Cell<u32>),
-    /// Always use this one lifetime.
-    Exact(Region),
-    /// Less or more than one lifetime were found, error on unspecified.
-    Error,
-    /// Forbid lifetime elision inside of a larger scope where it would be
-    /// permitted. For example, in let position impl trait.
-    Forbid,
-}
-
 type ScopeRef<'a> = &'a Scope<'a>;
 
 const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
@@ -486,9 +445,6 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::
             let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
             ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
         }
-        Region::LateBoundAnon(_, _, anon_idx) => {
-            ty::BoundVariableKind::Region(ty::BrAnon(*anon_idx))
-        }
         _ => bug!("{:?} is not a late region", region),
     }
 }
@@ -623,7 +579,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 next_early_index,
                 opaque_type_parent: false,
                 scope_type: BinderScopeType::Normal,
-                allow_late_bound: true,
                 where_bound_origin: None,
             };
 
@@ -664,8 +619,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
                 // No lifetime parameters, but implied 'static.
-                let scope = Scope::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE };
-                self.with(scope, |this| intravisit::walk_item(this, item));
+                self.with(Scope::Elision { s: self.scope }, |this| {
+                    intravisit::walk_item(this, item)
+                });
             }
             hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
                 // Opaque types are visited when we visit the
@@ -741,7 +697,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     opaque_type_parent: true,
                     scope_type: BinderScopeType::Normal,
                     s: ROOT_SCOPE,
-                    allow_late_bound: false,
                     where_bound_origin: None,
                 };
                 self.with(scope, |this| {
@@ -794,7 +749,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     next_early_index,
                     opaque_type_parent: false,
                     scope_type: BinderScopeType::Normal,
-                    allow_late_bound: true,
                     where_bound_origin: None,
                 };
                 self.with(scope, |this| {
@@ -819,13 +773,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         // `Box<dyn Debug + 'static>`.
                         self.resolve_object_lifetime_default(lifetime)
                     }
-                    LifetimeName::Implicit | LifetimeName::Underscore => {
+                    LifetimeName::Infer => {
                         // If the user writes `'_`, we use the *ordinary* elision
                         // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
                         // resolved the same as the `'_` in `&'_ Foo`.
                         //
                         // cc #48468
-                        self.resolve_elided_lifetimes(&[lifetime])
                     }
                     LifetimeName::Param(..) | LifetimeName::Static => {
                         // If the user wrote an explicit name, use that.
@@ -860,7 +813,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         // position impl Trait
                         let scope = Scope::TraitRefBoundary { s: self.scope };
                         self.with(scope, |this| {
-                            let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope };
+                            let scope = Scope::Elision { s: this.scope };
                             this.with(scope, |this| {
                                 intravisit::walk_item(this, opaque_ty);
                             })
@@ -936,7 +889,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let mut index = self.next_early_index_for_opaque_type();
                 debug!(?index);
 
-                let mut elision = None;
                 let mut lifetimes = FxIndexMap::default();
                 let mut non_lifetime_count = 0;
                 debug!(?generics.params);
@@ -945,15 +897,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         GenericParamKind::Lifetime { .. } => {
                             let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, &param);
                             lifetimes.insert(def_id, reg);
-                            if let hir::ParamName::Plain(Ident {
-                                name: kw::UnderscoreLifetime,
-                                ..
-                            }) = param.name
-                            {
-                                // Pick the elided lifetime "definition" if one exists
-                                // and use it to make an elision scope.
-                                elision = Some(reg);
-                            }
                         }
                         GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
                             non_lifetime_count += 1;
@@ -963,51 +906,24 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let next_early_index = index + non_lifetime_count;
                 self.map.late_bound_vars.insert(ty.hir_id, vec![]);
 
-                if let Some(elision_region) = elision {
-                    let scope =
-                        Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope };
-                    self.with(scope, |this| {
-                        let scope = Scope::Binder {
-                            hir_id: ty.hir_id,
-                            lifetimes,
-                            next_early_index,
-                            s: this.scope,
-                            opaque_type_parent: false,
-                            scope_type: BinderScopeType::Normal,
-                            allow_late_bound: false,
-                            where_bound_origin: None,
-                        };
-                        this.with(scope, |this| {
-                            this.visit_generics(generics);
-                            let scope = Scope::TraitRefBoundary { s: this.scope };
-                            this.with(scope, |this| {
-                                for bound in bounds {
-                                    this.visit_param_bound(bound);
-                                }
-                            })
-                        });
-                    });
-                } else {
-                    let scope = Scope::Binder {
-                        hir_id: ty.hir_id,
-                        lifetimes,
-                        next_early_index,
-                        s: self.scope,
-                        opaque_type_parent: false,
-                        scope_type: BinderScopeType::Normal,
-                        allow_late_bound: false,
-                        where_bound_origin: None,
-                    };
-                    self.with(scope, |this| {
-                        let scope = Scope::TraitRefBoundary { s: this.scope };
-                        this.with(scope, |this| {
-                            this.visit_generics(generics);
-                            for bound in bounds {
-                                this.visit_param_bound(bound);
-                            }
-                        })
-                    });
-                }
+                let scope = Scope::Binder {
+                    hir_id: ty.hir_id,
+                    lifetimes,
+                    next_early_index,
+                    s: self.scope,
+                    opaque_type_parent: false,
+                    scope_type: BinderScopeType::Normal,
+                    where_bound_origin: None,
+                };
+                self.with(scope, |this| {
+                    let scope = Scope::TraitRefBoundary { s: this.scope };
+                    this.with(scope, |this| {
+                        this.visit_generics(generics);
+                        for bound in bounds {
+                            this.visit_param_bound(bound);
+                        }
+                    })
+                });
             }
             _ => intravisit::walk_ty(self, ty),
         }
@@ -1051,7 +967,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     s: self.scope,
                     opaque_type_parent: true,
                     scope_type: BinderScopeType::Normal,
-                    allow_late_bound: false,
                     where_bound_origin: None,
                 };
                 self.with(scope, |this| {
@@ -1113,7 +1028,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     s: self.scope,
                     opaque_type_parent: true,
                     scope_type: BinderScopeType::Normal,
-                    allow_late_bound: true,
                     where_bound_origin: None,
                 };
                 self.with(scope, |this| {
@@ -1135,15 +1049,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     #[tracing::instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         match lifetime_ref.name {
-            hir::LifetimeName::ImplicitObjectLifetimeDefault
-            | hir::LifetimeName::Implicit
-            | hir::LifetimeName::Underscore => self.resolve_elided_lifetimes(&[lifetime_ref]),
             hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
             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`.
             hir::LifetimeName::Error => {}
+            // Those will be resolved by typechecking.
+            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
         }
     }
 
@@ -1156,12 +1069,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
+    fn visit_fn(
+        &mut self,
+        fk: intravisit::FnKind<'tcx>,
+        fd: &'tcx hir::FnDecl<'tcx>,
+        body_id: hir::BodyId,
+        _: Span,
+        _: hir::HirId,
+    ) {
         let output = match fd.output {
             hir::FnRetTy::DefaultReturn(_) => None,
             hir::FnRetTy::Return(ref ty) => Some(&**ty),
         };
-        self.visit_fn_like_elision(&fd.inputs, output);
+        self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
+        intravisit::walk_fn_kind(self, fk);
+        self.visit_nested_body(body_id)
     }
 
     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
@@ -1219,7 +1141,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                             next_early_index,
                             opaque_type_parent: false,
                             scope_type: BinderScopeType::Normal,
-                            allow_late_bound: true,
                             where_bound_origin: Some(origin),
                         };
                         this.with(scope, |this| {
@@ -1292,7 +1213,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     next_early_index: self.next_early_index(),
                     opaque_type_parent: false,
                     scope_type,
-                    allow_late_bound: true,
                     where_bound_origin: None,
                 };
                 self.with(scope, |this| {
@@ -1343,7 +1263,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             next_early_index,
             opaque_type_parent: false,
             scope_type,
-            allow_late_bound: true,
             where_bound_origin: None,
         };
         self.with(scope, |this| {
@@ -1597,7 +1516,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             s: self.scope,
             opaque_type_parent: true,
             scope_type: BinderScopeType::Normal,
-            allow_late_bound: true,
             where_bound_origin: None,
         };
         self.with(scope, walk);
@@ -1773,30 +1691,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         );
 
         if generic_args.parenthesized {
-            self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
+            self.visit_fn_like_elision(
+                generic_args.inputs(),
+                Some(generic_args.bindings[0].ty()),
+                false,
+            );
             return;
         }
 
-        let mut elide_lifetimes = true;
-        let lifetimes: Vec<_> = generic_args
-            .args
-            .iter()
-            .filter_map(|arg| match arg {
-                hir::GenericArg::Lifetime(lt) => {
-                    if !lt.is_elided() {
-                        elide_lifetimes = false;
-                    }
-                    Some(lt)
-                }
-                _ => None,
-            })
-            .collect();
-        // We short-circuit here if all are elided in order to pluralize
-        // possible errors
-        if elide_lifetimes {
-            self.resolve_elided_lifetimes(&lifetimes);
-        } else {
-            lifetimes.iter().for_each(|lt| self.visit_lifetime(lt));
+        for arg in generic_args.args {
+            if let hir::GenericArg::Lifetime(lt) = arg {
+                self.visit_lifetime(lt);
+            }
         }
 
         // Figure out if this is a type/trait segment,
@@ -2052,380 +1958,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         &mut self,
         inputs: &'tcx [hir::Ty<'tcx>],
         output: Option<&'tcx hir::Ty<'tcx>>,
+        in_closure: bool,
     ) {
-        debug!("visit_fn_like_elision: enter");
-        let mut scope = &*self.scope;
-        let hir_id = loop {
-            match scope {
-                Scope::Binder { hir_id, allow_late_bound: true, .. } => {
-                    break *hir_id;
-                }
-                Scope::ObjectLifetimeDefault { ref s, .. }
-                | Scope::Elision { ref s, .. }
-                | Scope::Supertrait { ref s, .. }
-                | Scope::TraitRefBoundary { ref s, .. } => {
-                    scope = *s;
-                }
-                Scope::Root
-                | Scope::Body { .. }
-                | Scope::Binder { allow_late_bound: false, .. } => {
-                    // See issues #83907 and #83693. Just bail out from looking inside.
-                    // See the issue #95023 for not allowing late bound
-                    self.tcx.sess.delay_span_bug(
-                        rustc_span::DUMMY_SP,
-                        "In fn_like_elision without appropriate scope above",
-                    );
-                    return;
-                }
-            }
-        };
-        // While not strictly necessary, we gather anon lifetimes *before* actually
-        // visiting the argument types.
-        let mut gather = GatherAnonLifetimes { anon_count: 0 };
-        for input in inputs {
-            gather.visit_ty(input);
-        }
-        trace!(?gather.anon_count);
-        let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default();
-        let named_late_bound_vars = late_bound_vars.len() as u32;
-        late_bound_vars.extend(
-            (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))),
-        );
-        let arg_scope = Scope::Elision {
-            elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)),
-            s: self.scope,
-        };
-        self.with(arg_scope, |this| {
+        self.with(Scope::Elision { s: self.scope }, |this| {
             for input in inputs {
                 this.visit_ty(input);
             }
-        });
-
-        let Some(output) = output else { return };
-
-        debug!("determine output");
-
-        // Figure out if there's a body we can get argument names from,
-        // and whether there's a `self` argument (treated specially).
-        let mut assoc_item_kind = None;
-        let mut impl_self = None;
-        let parent = self.tcx.hir().get_parent_node(output.hir_id);
-        match self.tcx.hir().get(parent) {
-            // `fn` definitions and methods.
-            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) => {}
-
-            Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) => {
-                if let hir::ItemKind::Trait(.., ref trait_items) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
-                {
-                    assoc_item_kind =
-                        trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind);
-                }
-            }
-
-            Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, _), .. }) => {
-                if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) =
-                    self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
-                {
-                    impl_self = Some(self_ty);
-                    assoc_item_kind =
-                        items.iter().find(|ii| ii.id.hir_id() == parent).map(|ii| ii.kind);
-                }
-            }
-
-            // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
-            Node::ForeignItem(_) | Node::Ty(_) | Node::TraitRef(_) => {},
-
-            Node::TypeBinding(_) if let Node::TraitRef(_) = self.tcx.hir().get(self.tcx.hir().get_parent_node(parent)) => {},
-
-            // Everything else (only closures?) doesn't
-            // actually enjoy elision in return types.
-            _ => {
-                self.visit_ty(output);
-                return;
-            }
-        };
-
-        let has_self = match assoc_item_kind {
-            Some(hir::AssocItemKind::Fn { has_self }) => has_self,
-            _ => false,
-        };
-
-        // In accordance with the rules for lifetime elision, we can determine
-        // what region to use for elision in the output type in two ways.
-        // First (determined here), if `self` is by-reference, then the
-        // implied output region is the region of the self parameter.
-        if has_self {
-            struct SelfVisitor<'a> {
-                map: &'a NamedRegionMap,
-                impl_self: Option<&'a hir::TyKind<'a>>,
-                lifetime: Set1<Region>,
-            }
-
-            impl SelfVisitor<'_> {
-                // Look for `self: &'a Self` - also desugared from `&'a self`,
-                // and if that matches, use it for elision and return early.
-                fn is_self_ty(&self, res: Res) -> bool {
-                    if let Res::SelfTy { .. } = res {
-                        return true;
-                    }
-
-                    // Can't always rely on literal (or implied) `Self` due
-                    // to the way elision rules were originally specified.
-                    if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) =
-                        self.impl_self
-                    {
-                        match path.res {
-                            // Permit the types that unambiguously always
-                            // result in the same type constructor being used
-                            // (it can't differ between `Self` and `self`).
-                            Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _)
-                            | Res::PrimTy(_) => return res == path.res,
-                            _ => {}
-                        }
-                    }
-
-                    false
-                }
-            }
-
-            impl<'a> Visitor<'a> for SelfVisitor<'a> {
-                fn visit_ty(&mut self, ty: &'a hir::Ty<'a>) {
-                    if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.kind {
-                        if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.kind
-                        {
-                            if self.is_self_ty(path.res) {
-                                if let Some(lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
-                                    self.lifetime.insert(*lifetime);
-                                }
-                            }
-                        }
-                    }
-                    intravisit::walk_ty(self, ty)
-                }
-            }
-
-            let mut visitor = SelfVisitor {
-                map: self.map,
-                impl_self: impl_self.map(|ty| &ty.kind),
-                lifetime: Set1::Empty,
-            };
-            visitor.visit_ty(&inputs[0]);
-            if let Set1::One(lifetime) = visitor.lifetime {
-                let scope = Scope::Elision { elide: Elide::Exact(lifetime), s: self.scope };
-                self.with(scope, |this| this.visit_ty(output));
-                return;
+            if !in_closure && let Some(output) = output {
+                this.visit_ty(output);
             }
-        }
-
-        // Second, if there was exactly one lifetime (either a substitution or a
-        // reference) in the arguments, then any anonymous regions in the output
-        // have that lifetime.
-        let mut possible_implied_output_region = None;
-        let mut lifetime_count = 0;
-        for input in inputs.iter().skip(has_self as usize) {
-            let mut gather = GatherLifetimes {
-                map: self.map,
-                outer_index: ty::INNERMOST,
-                have_bound_regions: false,
-                lifetimes: Default::default(),
-            };
-            gather.visit_ty(input);
-
-            lifetime_count += gather.lifetimes.len();
-
-            if lifetime_count == 1 && gather.lifetimes.len() == 1 {
-                // there's a chance that the unique lifetime of this
-                // iteration will be the appropriate lifetime for output
-                // parameters, so lets store it.
-                possible_implied_output_region = gather.lifetimes.iter().cloned().next();
-            }
-        }
-
-        let elide = if lifetime_count == 1 {
-            Elide::Exact(possible_implied_output_region.unwrap())
-        } else {
-            Elide::Error
-        };
-
-        debug!(?elide);
-
-        let scope = Scope::Elision { elide, s: self.scope };
-        self.with(scope, |this| this.visit_ty(output));
-
-        struct GatherLifetimes<'a> {
-            map: &'a NamedRegionMap,
-            outer_index: ty::DebruijnIndex,
-            have_bound_regions: bool,
-            lifetimes: FxHashSet<Region>,
-        }
-
-        impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> {
-            fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
-                if let hir::TyKind::BareFn(_) = ty.kind {
-                    self.outer_index.shift_in(1);
-                }
-                match ty.kind {
-                    hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
-                        for bound in bounds {
-                            self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
-                        }
-
-                        // Stay on the safe side and don't include the object
-                        // lifetime default (which may not end up being used).
-                        if !lifetime.is_elided() {
-                            self.visit_lifetime(lifetime);
-                        }
-                    }
-                    _ => {
-                        intravisit::walk_ty(self, ty);
-                    }
-                }
-                if let hir::TyKind::BareFn(_) = ty.kind {
-                    self.outer_index.shift_out(1);
-                }
-            }
-
-            fn visit_generic_param(&mut self, param: &hir::GenericParam<'_>) {
-                if let hir::GenericParamKind::Lifetime { .. } = param.kind {
-                    // FIXME(eddyb) Do we want this? It only makes a difference
-                    // if this `for<'a>` lifetime parameter is never used.
-                    self.have_bound_regions = true;
-                }
-
-                intravisit::walk_generic_param(self, param);
-            }
-
-            fn visit_poly_trait_ref(
-                &mut self,
-                trait_ref: &hir::PolyTraitRef<'_>,
-                modifier: hir::TraitBoundModifier,
-            ) {
-                self.outer_index.shift_in(1);
-                intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
-                self.outer_index.shift_out(1);
-            }
-
-            fn visit_param_bound(&mut self, bound: &hir::GenericBound<'_>) {
-                if let hir::GenericBound::LangItemTrait { .. } = bound {
-                    self.outer_index.shift_in(1);
-                    intravisit::walk_param_bound(self, bound);
-                    self.outer_index.shift_out(1);
-                } else {
-                    intravisit::walk_param_bound(self, bound);
-                }
-            }
-
-            fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
-                if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
-                    match lifetime {
-                        Region::LateBound(debruijn, _, _)
-                        | Region::LateBoundAnon(debruijn, _, _)
-                            if debruijn < self.outer_index =>
-                        {
-                            self.have_bound_regions = true;
-                        }
-                        _ => {
-                            // FIXME(jackh726): nested trait refs?
-                            self.lifetimes.insert(lifetime.shifted_out_to_binder(self.outer_index));
-                        }
-                    }
-                }
-            }
-        }
-
-        struct GatherAnonLifetimes {
-            anon_count: u32,
-        }
-        impl<'v> Visitor<'v> for GatherAnonLifetimes {
-            #[instrument(skip(self), level = "trace")]
-            fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
-                // If we enter a `BareFn`, then we enter a *new* binding scope
-                if let hir::TyKind::BareFn(_) = ty.kind {
-                    return;
-                }
-                intravisit::walk_ty(self, ty);
-            }
-
-            fn visit_generic_args(
-                &mut self,
-                path_span: Span,
-                generic_args: &'v hir::GenericArgs<'v>,
-            ) {
-                // parenthesized args enter a new elision scope
-                if generic_args.parenthesized {
-                    return;
-                }
-                intravisit::walk_generic_args(self, path_span, generic_args)
-            }
-
-            #[instrument(skip(self), level = "trace")]
-            fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
-                if lifetime_ref.is_elided() {
-                    self.anon_count += 1;
-                }
-            }
-        }
-    }
-
-    fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
-        debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs);
-
-        if lifetime_refs.is_empty() {
-            return;
-        }
-
-        let mut late_depth = 0;
-        let mut scope = self.scope;
-        loop {
-            match *scope {
-                // Do not assign any resolution, it will be inferred.
-                Scope::Body { .. } => return,
-
-                Scope::Root => break,
-
-                Scope::Binder { s, scope_type, .. } => {
-                    match scope_type {
-                        BinderScopeType::Normal => late_depth += 1,
-                        BinderScopeType::Concatenating => {}
-                    }
-                    scope = s;
-                }
-
-                Scope::Elision {
-                    elide: Elide::FreshLateAnon(named_late_bound_vars, ref counter),
-                    ..
-                } => {
-                    for lifetime_ref in lifetime_refs {
-                        let lifetime =
-                            Region::late_anon(named_late_bound_vars, counter).shifted(late_depth);
-
-                        self.insert_lifetime(lifetime_ref, lifetime);
-                    }
-                    return;
-                }
-
-                Scope::Elision { elide: Elide::Exact(l), .. } => {
-                    let lifetime = l.shifted(late_depth);
-                    for lifetime_ref in lifetime_refs {
-                        self.insert_lifetime(lifetime_ref, lifetime);
-                    }
-                    return;
-                }
-
-                Scope::Elision { elide: Elide::Error, .. }
-                | Scope::Elision { elide: Elide::Forbid, .. } => break,
-
-                Scope::ObjectLifetimeDefault { s, .. }
-                | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. } => {
-                    scope = s;
-                }
-            }
-        }
-
-        for lt in lifetime_refs {
-            self.tcx.sess.delay_span_bug(lt.span, "Missing lifetime specifier");
+        });
+        if in_closure && let Some(output) = output {
+            self.visit_ty(output);
         }
     }
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 58f4f02052f..08e8e6f7d0f 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -221,14 +221,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 tcx.mk_region(ty::ReLateBound(debruijn, br))
             }
 
-            Some(rl::Region::LateBoundAnon(debruijn, index, anon_index)) => {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::from_u32(index),
-                    kind: ty::BrAnon(anon_index),
-                };
-                tcx.mk_region(ty::ReLateBound(debruijn, br))
-            }
-
             Some(rl::Region::EarlyBound(index, id)) => {
                 let name = lifetime_name(id.expect_local());
                 tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name }))
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 0e78c60ca5b..60c0694ca0e 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1346,16 +1346,8 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
 
             match self.tcx.named_region(lt.hir_id) {
                 Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
-                Some(
-                    rl::Region::LateBound(debruijn, _, _)
-                    | rl::Region::LateBoundAnon(debruijn, _, _),
-                ) if debruijn < self.outer_index => {}
-                Some(
-                    rl::Region::LateBound(..)
-                    | rl::Region::LateBoundAnon(..)
-                    | rl::Region::Free(..),
-                )
-                | None => {
+                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);
                 }
             }
diff --git a/src/test/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs b/src/test/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs
new file mode 100644
index 00000000000..929b82bfc43
--- /dev/null
+++ b/src/test/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs
@@ -0,0 +1,24 @@
+// check-pass
+// Verify that we do not ICE when anonymous lifetimes appear inside an AnonConst.
+
+pub struct EntriesBuffer(Box<[[u8; HashesEntry::LEN]; 5]>);
+
+impl EntriesBuffer {
+    pub fn iter_child_buffers(&mut self) -> impl Iterator<Item = &mut [u8; HashesEntry::LEN]> {
+        self.0.iter_mut()
+    }
+
+    pub fn iter_child_buffers_explicit(
+        &mut self,
+    ) -> impl Iterator<Item = &mut [u8; HashesEntry::<'_>::LEN]> {
+        self.0.iter_mut()
+    }
+}
+
+pub struct HashesEntry<'a>(&'a [u8]);
+
+impl HashesEntry<'_> {
+    pub const LEN: usize = 1;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 826353aafc0..3f69cc20388 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -615,7 +615,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::Empty && lifetime.name.ident().name != kw::StaticLifetime {
+        if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.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 945880d2147..a0ca7e6ff1e 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -166,7 +166,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
     // - There's only one output lifetime bound using `+ '_`
     // - All input lifetimes are explicitly bound to the output
     input_lifetimes.is_empty()
-        || (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Underscore))
+        || (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
         || input_lifetimes
             .iter()
             .all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 8534d8a29f1..3c5ea2d9414 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -351,7 +351,7 @@ impl fmt::Display for RefPrefix {
                 name.fmt(f)?;
                 f.write_char(' ')?;
             },
-            LifetimeName::Underscore => f.write_str("'_ ")?,
+            LifetimeName::Infer => f.write_str("'_ ")?,
             LifetimeName::Static => f.write_str("'static ")?,
             _ => (),
         }