rustc_hir_analysis/collect/
resolve_bound_vars.rs

1//! Resolution of early vs late bound lifetimes.
2//!
3//! Name resolution for lifetimes is performed on the AST and embedded into HIR. From this
4//! information, typechecking needs to transform the lifetime parameters into bound lifetimes.
5//! Lifetimes can be early-bound or late-bound. Construction of typechecking terms needs to visit
6//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
7//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
8
9use std::cell::RefCell;
10use std::fmt;
11use std::ops::ControlFlow;
12
13use rustc_ast::visit::walk_list;
14use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
15use rustc_errors::ErrorGuaranteed;
16use rustc_hir::def::{DefKind, Res};
17use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
18use rustc_hir::{
19    self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
20};
21use rustc_macros::extension;
22use rustc_middle::hir::nested_filter;
23use rustc_middle::middle::resolve_bound_vars::*;
24use rustc_middle::query::Providers;
25use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
26use rustc_middle::{bug, span_bug};
27use rustc_span::def_id::{DefId, LocalDefId};
28use rustc_span::{Ident, Span, sym};
29use tracing::{debug, debug_span, instrument};
30
31use crate::errors;
32
33#[extension(trait RegionExt)]
34impl ResolvedArg {
35    fn early(param: &GenericParam<'_>) -> ResolvedArg {
36        ResolvedArg::EarlyBound(param.def_id)
37    }
38
39    fn late(idx: u32, param: &GenericParam<'_>) -> ResolvedArg {
40        ResolvedArg::LateBound(ty::INNERMOST, idx, param.def_id)
41    }
42
43    fn id(&self) -> Option<LocalDefId> {
44        match *self {
45            ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
46
47            ResolvedArg::EarlyBound(id)
48            | ResolvedArg::LateBound(_, _, id)
49            | ResolvedArg::Free(_, id) => Some(id),
50        }
51    }
52
53    fn shifted(self, amount: u32) -> ResolvedArg {
54        match self {
55            ResolvedArg::LateBound(debruijn, idx, id) => {
56                ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
57            }
58            _ => self,
59        }
60    }
61}
62
63struct BoundVarContext<'a, 'tcx> {
64    tcx: TyCtxt<'tcx>,
65    rbv: &'a mut ResolveBoundVars,
66    scope: ScopeRef<'a>,
67}
68
69#[derive(Debug)]
70enum Scope<'a> {
71    /// Declares lifetimes, and each can be early-bound or late-bound.
72    /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
73    /// it should be shifted by the number of `Binder`s in between the
74    /// declaration `Binder` and the location it's referenced from.
75    Binder {
76        /// We use an IndexMap here because we want these lifetimes in order
77        /// for diagnostics.
78        bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
79
80        scope_type: BinderScopeType,
81
82        /// The late bound vars for a given item are stored by `HirId` to be
83        /// queried later. However, if we enter an elision scope, we have to
84        /// later append the elided bound vars to the list and need to know what
85        /// to append to.
86        hir_id: HirId,
87
88        s: ScopeRef<'a>,
89
90        /// If this binder comes from a where clause, specify how it was created.
91        /// This is used to diagnose inaccessible lifetimes in APIT:
92        /// ```ignore (illustrative)
93        /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
94        /// ```
95        where_bound_origin: Option<hir::PredicateOrigin>,
96    },
97
98    /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
99    /// if this is a fn body, otherwise the original definitions are used.
100    /// Unspecified lifetimes are inferred, unless an elision scope is nested,
101    /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
102    Body {
103        id: hir::BodyId,
104        s: ScopeRef<'a>,
105    },
106
107    /// Use a specific lifetime (if `Some`) or leave it unset (to be
108    /// inferred in a function body or potentially error outside one),
109    /// for the default choice of lifetime in a trait object type.
110    ObjectLifetimeDefault {
111        lifetime: Option<ResolvedArg>,
112        s: ScopeRef<'a>,
113    },
114
115    /// When we have nested trait refs, we concatenate late bound vars for inner
116    /// trait refs from outer ones. But we also need to include any HRTB
117    /// lifetimes encountered when identifying the trait that an associated type
118    /// is declared on.
119    Supertrait {
120        bound_vars: Vec<ty::BoundVariableKind>,
121        s: ScopeRef<'a>,
122    },
123
124    TraitRefBoundary {
125        s: ScopeRef<'a>,
126    },
127
128    /// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given:
129    /// `fn foo<'a>() -> impl MyTrait<'a> { ... }`
130    ///
131    /// HIR tells us that `'a` refer to the lifetime bound on `foo`.
132    /// However, typeck and borrowck for opaques work based on using a new generic type.
133    /// `type MyAnonTy<'b> = impl MyTrait<'b>;`
134    ///
135    /// This scope collects the mapping `'a -> 'b`.
136    Opaque {
137        /// The opaque type we are traversing.
138        def_id: LocalDefId,
139        /// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`.
140        captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
141
142        s: ScopeRef<'a>,
143    },
144
145    /// Disallows capturing late-bound vars from parent scopes.
146    ///
147    /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
148    /// since we don't do something more correct like replacing any captured
149    /// late-bound vars with early-bound params in the const's own generics.
150    LateBoundary {
151        s: ScopeRef<'a>,
152        what: &'static str,
153        deny_late_regions: bool,
154    },
155
156    Root {
157        opt_parent_item: Option<LocalDefId>,
158    },
159}
160
161impl<'a> Scope<'a> {
162    // A helper for debugging scopes without printing parent scopes
163    fn debug_truncated(&self) -> impl fmt::Debug {
164        fmt::from_fn(move |f| match self {
165            Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
166                .debug_struct("Binder")
167                .field("bound_vars", bound_vars)
168                .field("scope_type", scope_type)
169                .field("hir_id", hir_id)
170                .field("where_bound_origin", where_bound_origin)
171                .field("s", &"..")
172                .finish(),
173            Self::Opaque { captures, def_id, s: _ } => f
174                .debug_struct("Opaque")
175                .field("def_id", def_id)
176                .field("captures", &captures.borrow())
177                .field("s", &"..")
178                .finish(),
179            Self::Body { id, s: _ } => {
180                f.debug_struct("Body").field("id", id).field("s", &"..").finish()
181            }
182            Self::ObjectLifetimeDefault { lifetime, s: _ } => f
183                .debug_struct("ObjectLifetimeDefault")
184                .field("lifetime", lifetime)
185                .field("s", &"..")
186                .finish(),
187            Self::Supertrait { bound_vars, s: _ } => f
188                .debug_struct("Supertrait")
189                .field("bound_vars", bound_vars)
190                .field("s", &"..")
191                .finish(),
192            Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
193            Self::LateBoundary { s: _, what, deny_late_regions } => f
194                .debug_struct("LateBoundary")
195                .field("what", what)
196                .field("deny_late_regions", deny_late_regions)
197                .finish(),
198            Self::Root { opt_parent_item } => {
199                f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
200            }
201        })
202    }
203}
204
205#[derive(Copy, Clone, Debug)]
206enum BinderScopeType {
207    /// Any non-concatenating binder scopes.
208    Normal,
209    /// Within a syntactic trait ref, there may be multiple poly trait refs that
210    /// are nested (under the `associated_type_bounds` feature). The binders of
211    /// the inner poly trait refs are extended from the outer poly trait refs
212    /// and don't increase the late bound depth. If you had
213    /// `T: for<'a>  Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope
214    /// would be `Concatenating`. This also used in trait refs in where clauses
215    /// where we have two binders `for<> T: for<> Foo` (I've intentionally left
216    /// out any lifetimes because they aren't needed to show the two scopes).
217    /// The inner `for<>` has a scope of `Concatenating`.
218    Concatenating,
219}
220
221type ScopeRef<'a> = &'a Scope<'a>;
222
223pub(crate) fn provide(providers: &mut Providers) {
224    *providers = Providers {
225        resolve_bound_vars,
226
227        named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
228        is_late_bound_map,
229        object_lifetime_default,
230        late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
231        opaque_captured_lifetimes: |tcx, id| {
232            &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
233                .opaque_captured_lifetimes
234                .get(&id)
235                .map_or(&[][..], |x| &x[..])
236        },
237
238        ..*providers
239    };
240}
241
242/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
243/// You should not read the result of this query directly, but rather use
244/// `named_variable_map`, `late_bound_vars_map`, etc.
245#[instrument(level = "debug", skip(tcx))]
246fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
247    let mut rbv = ResolveBoundVars::default();
248    let mut visitor =
249        BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
250    match tcx.hir_owner_node(local_def_id) {
251        hir::OwnerNode::Item(item) => visitor.visit_item(item),
252        hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
253        hir::OwnerNode::TraitItem(item) => {
254            let scope =
255                Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
256            visitor.scope = &scope;
257            visitor.visit_trait_item(item)
258        }
259        hir::OwnerNode::ImplItem(item) => {
260            let scope =
261                Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
262            visitor.scope = &scope;
263            visitor.visit_impl_item(item)
264        }
265        hir::OwnerNode::Crate(_) => {}
266        hir::OwnerNode::Synthetic => unreachable!(),
267    }
268
269    debug!(?rbv.defs);
270    debug!(?rbv.late_bound_vars);
271    debug!(?rbv.opaque_captured_lifetimes);
272    rbv
273}
274
275fn late_arg_as_bound_arg<'tcx>(
276    tcx: TyCtxt<'tcx>,
277    param: &GenericParam<'tcx>,
278) -> ty::BoundVariableKind {
279    let def_id = param.def_id.to_def_id();
280    let name = tcx.item_name(def_id);
281    match param.kind {
282        GenericParamKind::Lifetime { .. } => {
283            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
284        }
285        GenericParamKind::Type { .. } => {
286            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name))
287        }
288        GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
289    }
290}
291
292/// Turn a [`ty::GenericParamDef`] into a bound arg. Generally, this should only
293/// be used when turning early-bound vars into late-bound vars when lowering
294/// return type notation.
295fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
296    match param.kind {
297        ty::GenericParamDefKind::Lifetime => {
298            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id, param.name))
299        }
300        ty::GenericParamDefKind::Type { .. } => {
301            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
302        }
303        ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
304    }
305}
306
307/// Whether this opaque always captures lifetimes in scope.
308/// Right now, this is all RPITIT and TAITs, and when the opaque
309/// is coming from a span corresponding to edition 2024.
310fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
311    match opaque.origin {
312        // if the opaque has the `use<...>` syntax, the user is telling us that they only want
313        // to account for those lifetimes, so do not try to be clever.
314        _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
315        hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
316        _ if opaque.span.at_least_rust_2024() => true,
317        hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
318    }
319}
320
321impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
322    /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
323    fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
324        let mut scope = self.scope;
325        let mut supertrait_bound_vars = vec![];
326        loop {
327            match scope {
328                Scope::Body { .. } | Scope::Root { .. } => {
329                    break (vec![], BinderScopeType::Normal);
330                }
331
332                Scope::Opaque { s, .. }
333                | Scope::ObjectLifetimeDefault { s, .. }
334                | Scope::LateBoundary { s, .. } => {
335                    scope = s;
336                }
337
338                Scope::Supertrait { s, bound_vars } => {
339                    supertrait_bound_vars = bound_vars.clone();
340                    scope = s;
341                }
342
343                Scope::TraitRefBoundary { .. } => {
344                    // We should only see super trait lifetimes if there is a `Binder` above
345                    // though this may happen when we call `poly_trait_ref_binder_info` with
346                    // an (erroneous, #113423) associated return type bound in an impl header.
347                    if !supertrait_bound_vars.is_empty() {
348                        self.tcx.dcx().delayed_bug(format!(
349                            "found supertrait lifetimes without a binder to append \
350                                them to: {supertrait_bound_vars:?}"
351                        ));
352                    }
353                    break (vec![], BinderScopeType::Normal);
354                }
355
356                Scope::Binder { hir_id, .. } => {
357                    // Nested poly trait refs have the binders concatenated
358                    let mut full_binders =
359                        self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
360                    full_binders.extend(supertrait_bound_vars);
361                    break (full_binders, BinderScopeType::Concatenating);
362                }
363            }
364        }
365    }
366
367    fn visit_poly_trait_ref_inner(
368        &mut self,
369        trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
370        non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
371    ) {
372        debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
373
374        let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
375
376        let initial_bound_vars = binders.len() as u32;
377        let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
378        let binders_iter =
379            trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
380                let arg = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
381                bound_vars.insert(param.def_id, arg);
382                late_arg_as_bound_arg(self.tcx, param)
383            });
384        binders.extend(binders_iter);
385
386        if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
387            deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
388        }
389
390        debug!(?binders);
391        self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
392
393        // Always introduce a scope here, even if this is in a where clause and
394        // we introduced the binders around the bounded Ty. In that case, we
395        // just reuse the concatenation functionality also present in nested trait
396        // refs.
397        let scope = Scope::Binder {
398            hir_id: trait_ref.trait_ref.hir_ref_id,
399            bound_vars,
400            s: self.scope,
401            scope_type,
402            where_bound_origin: None,
403        };
404        self.with(scope, |this| {
405            walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
406            this.visit_trait_ref(&trait_ref.trait_ref);
407        });
408    }
409}
410
411enum NonLifetimeBinderAllowed {
412    Deny(&'static str),
413    Allow,
414}
415
416impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
417    type NestedFilter = nested_filter::OnlyBodies;
418
419    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
420        self.tcx
421    }
422
423    fn visit_nested_body(&mut self, body: hir::BodyId) {
424        let body = self.tcx.hir_body(body);
425        self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
426            this.visit_body(body);
427        });
428    }
429
430    fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
431        if let hir::ExprKind::Closure(hir::Closure {
432            binder, bound_generic_params, fn_decl, ..
433        }) = e.kind
434        {
435            if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
436                fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
437                    /// Look for `_` anywhere in the signature of a `for<> ||` closure.
438                    /// This is currently disallowed.
439                    struct FindInferInClosureWithBinder;
440                    impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
441                        type Result = ControlFlow<Span>;
442
443                        fn visit_infer(
444                            &mut self,
445                            _inf_id: HirId,
446                            inf_span: Span,
447                            _kind: InferKind<'v>,
448                        ) -> Self::Result {
449                            ControlFlow::Break(inf_span)
450                        }
451                    }
452                    FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value()
453                }
454
455                let infer_in_rt_sp = match fn_decl.output {
456                    hir::FnRetTy::DefaultReturn(sp) => Some(sp),
457                    hir::FnRetTy::Return(ty) => span_of_infer(ty),
458                };
459
460                let infer_spans = fn_decl
461                    .inputs
462                    .into_iter()
463                    .filter_map(span_of_infer)
464                    .chain(infer_in_rt_sp)
465                    .collect::<Vec<_>>();
466
467                if !infer_spans.is_empty() {
468                    self.tcx
469                        .dcx()
470                        .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
471                }
472            }
473
474            let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
475                bound_generic_params
476                    .iter()
477                    .enumerate()
478                    .map(|(late_bound_idx, param)| {
479                        (
480                            (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
481                            late_arg_as_bound_arg(self.tcx, param),
482                        )
483                    })
484                    .unzip();
485
486            deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
487
488            self.record_late_bound_vars(e.hir_id, binders);
489            let scope = Scope::Binder {
490                hir_id: e.hir_id,
491                bound_vars,
492                s: self.scope,
493                scope_type: BinderScopeType::Normal,
494                where_bound_origin: None,
495            };
496
497            self.with(scope, |this| {
498                // a closure has no bounds, so everything
499                // contained within is scoped within its binder.
500                intravisit::walk_expr(this, e)
501            });
502        } else {
503            intravisit::walk_expr(self, e)
504        }
505    }
506
507    /// Resolve the lifetimes inside the opaque type, and save them into
508    /// `opaque_captured_lifetimes`.
509    ///
510    /// This method has special handling for opaques that capture all lifetimes,
511    /// like async desugaring.
512    #[instrument(level = "debug", skip(self))]
513    fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
514        let captures = RefCell::new(FxIndexMap::default());
515
516        let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
517        if capture_all_in_scope_lifetimes {
518            let lifetime_ident = |def_id: LocalDefId| {
519                let name = self.tcx.item_name(def_id.to_def_id());
520                let span = self.tcx.def_span(def_id);
521                Ident::new(name, span)
522            };
523
524            // We list scopes outwards, this causes us to see lifetime parameters in reverse
525            // declaration order. In order to make it consistent with what `generics_of` might
526            // give, we will reverse the IndexMap after early captures.
527            let mut late_depth = 0;
528            let mut scope = self.scope;
529            let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
530            loop {
531                match *scope {
532                    Scope::Binder { ref bound_vars, scope_type, s, .. } => {
533                        for (&original_lifetime, &def) in bound_vars.iter().rev() {
534                            if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
535                                let def = def.shifted(late_depth);
536                                let ident = lifetime_ident(original_lifetime);
537                                self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
538                            }
539                        }
540                        match scope_type {
541                            BinderScopeType::Normal => late_depth += 1,
542                            BinderScopeType::Concatenating => {}
543                        }
544                        scope = s;
545                    }
546
547                    Scope::Root { mut opt_parent_item } => {
548                        while let Some(parent_item) = opt_parent_item {
549                            let parent_generics = self.tcx.generics_of(parent_item);
550                            for param in parent_generics.own_params.iter().rev() {
551                                if let ty::GenericParamDefKind::Lifetime = param.kind {
552                                    let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
553                                    let ident = lifetime_ident(param.def_id.expect_local());
554                                    self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
555                                }
556                            }
557                            opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
558                        }
559                        break;
560                    }
561
562                    Scope::Opaque { captures, def_id, s } => {
563                        opaque_capture_scopes.push((def_id, captures));
564                        late_depth = 0;
565                        scope = s;
566                    }
567
568                    Scope::Body { .. } => {
569                        bug!("{:?}", scope)
570                    }
571
572                    Scope::ObjectLifetimeDefault { s, .. }
573                    | Scope::Supertrait { s, .. }
574                    | Scope::TraitRefBoundary { s, .. }
575                    | Scope::LateBoundary { s, .. } => {
576                        scope = s;
577                    }
578                }
579            }
580            captures.borrow_mut().reverse();
581        }
582
583        let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
584        self.with(scope, |this| {
585            let scope = Scope::TraitRefBoundary { s: this.scope };
586            this.with(scope, |this| {
587                let scope = Scope::LateBoundary {
588                    s: this.scope,
589                    what: "nested `impl Trait`",
590                    // We can capture late-bound regions; we just don't duplicate
591                    // lifetime or const params, so we can't allow those.
592                    deny_late_regions: false,
593                };
594                this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
595            })
596        });
597
598        let captures = captures.into_inner().into_iter().collect();
599        debug!(?captures);
600        self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
601    }
602
603    #[instrument(level = "debug", skip(self))]
604    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
605        match &item.kind {
606            hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
607                if let Some(of_trait) = of_trait {
608                    self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
609                }
610            }
611            _ => {}
612        }
613        match item.kind {
614            hir::ItemKind::Fn { generics, .. } => {
615                self.visit_early_late(item.hir_id(), generics, |this| {
616                    intravisit::walk_item(this, item);
617                });
618            }
619
620            hir::ItemKind::ExternCrate(..)
621            | hir::ItemKind::Use(..)
622            | hir::ItemKind::Macro(..)
623            | hir::ItemKind::Mod(..)
624            | hir::ItemKind::ForeignMod { .. }
625            | hir::ItemKind::Static(..)
626            | hir::ItemKind::GlobalAsm { .. } => {
627                // These sorts of items have no lifetime parameters at all.
628                intravisit::walk_item(self, item);
629            }
630            hir::ItemKind::TyAlias(_, _, generics)
631            | hir::ItemKind::Const(_, _, generics, _)
632            | hir::ItemKind::Enum(_, _, generics)
633            | hir::ItemKind::Struct(_, _, generics)
634            | hir::ItemKind::Union(_, _, generics)
635            | hir::ItemKind::Trait(_, _, _, generics, ..)
636            | hir::ItemKind::TraitAlias(_, generics, ..)
637            | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
638                // These kinds of items have only early-bound lifetime parameters.
639                self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
640            }
641        }
642    }
643
644    fn visit_precise_capturing_arg(
645        &mut self,
646        arg: &'tcx hir::PreciseCapturingArg<'tcx>,
647    ) -> Self::Result {
648        match *arg {
649            hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
650                LifetimeName::Param(def_id) => {
651                    self.resolve_lifetime_ref(def_id, lt);
652                }
653                LifetimeName::Error => {}
654                LifetimeName::ImplicitObjectLifetimeDefault
655                | LifetimeName::Infer
656                | LifetimeName::Static => {
657                    self.tcx.dcx().emit_err(errors::BadPreciseCapture {
658                        span: lt.ident.span,
659                        kind: "lifetime",
660                        found: format!("`{}`", lt.ident.name),
661                    });
662                }
663            },
664            hir::PreciseCapturingArg::Param(param) => match param.res {
665                Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
666                | Res::SelfTyParam { trait_: def_id } => {
667                    self.resolve_type_ref(def_id.expect_local(), param.hir_id);
668                }
669                Res::SelfTyAlias { alias_to, .. } => {
670                    self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
671                        span: param.ident.span,
672                        self_span: self.tcx.def_span(alias_to),
673                        what: self.tcx.def_descr(alias_to),
674                    });
675                }
676                res => {
677                    self.tcx.dcx().span_delayed_bug(
678                        param.ident.span,
679                        format!("expected type or const param, found {res:?}"),
680                    );
681                }
682            },
683        }
684    }
685
686    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
687        match item.kind {
688            hir::ForeignItemKind::Fn(_, _, generics) => {
689                self.visit_early_late(item.hir_id(), generics, |this| {
690                    intravisit::walk_foreign_item(this, item);
691                })
692            }
693            hir::ForeignItemKind::Static(..) => {
694                intravisit::walk_foreign_item(self, item);
695            }
696            hir::ForeignItemKind::Type => {
697                intravisit::walk_foreign_item(self, item);
698            }
699        }
700    }
701
702    #[instrument(level = "debug", skip(self))]
703    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
704        match ty.kind {
705            hir::TyKind::BareFn(c) => {
706                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
707                    .generic_params
708                    .iter()
709                    .enumerate()
710                    .map(|(late_bound_idx, param)| {
711                        (
712                            (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
713                            late_arg_as_bound_arg(self.tcx, param),
714                        )
715                    })
716                    .unzip();
717
718                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
719
720                self.record_late_bound_vars(ty.hir_id, binders);
721                let scope = Scope::Binder {
722                    hir_id: ty.hir_id,
723                    bound_vars,
724                    s: self.scope,
725                    scope_type: BinderScopeType::Normal,
726                    where_bound_origin: None,
727                };
728                self.with(scope, |this| {
729                    // a bare fn has no bounds, so everything
730                    // contained within is scoped within its binder.
731                    intravisit::walk_ty(this, ty);
732                });
733            }
734            hir::TyKind::UnsafeBinder(binder) => {
735                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
736                    binder
737                        .generic_params
738                        .iter()
739                        .enumerate()
740                        .map(|(late_bound_idx, param)| {
741                            (
742                                (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
743                                late_arg_as_bound_arg(self.tcx, param),
744                            )
745                        })
746                        .unzip();
747
748                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
749
750                self.record_late_bound_vars(ty.hir_id, binders);
751                let scope = Scope::Binder {
752                    hir_id: ty.hir_id,
753                    bound_vars,
754                    s: self.scope,
755                    scope_type: BinderScopeType::Normal,
756                    where_bound_origin: None,
757                };
758                self.with(scope, |this| {
759                    // a bare fn has no bounds, so everything
760                    // contained within is scoped within its binder.
761                    intravisit::walk_ty(this, ty);
762                });
763            }
764            hir::TyKind::TraitObject(bounds, lifetime) => {
765                let lifetime = lifetime.pointer();
766
767                debug!(?bounds, ?lifetime, "TraitObject");
768                let scope = Scope::TraitRefBoundary { s: self.scope };
769                self.with(scope, |this| {
770                    for bound in bounds {
771                        this.visit_poly_trait_ref_inner(
772                            bound,
773                            NonLifetimeBinderAllowed::Deny("trait object types"),
774                        );
775                    }
776                });
777                match lifetime.res {
778                    LifetimeName::ImplicitObjectLifetimeDefault => {
779                        // If the user does not write *anything*, we
780                        // use the object lifetime defaulting
781                        // rules. So e.g., `Box<dyn Debug>` becomes
782                        // `Box<dyn Debug + 'static>`.
783                        self.resolve_object_lifetime_default(&*lifetime)
784                    }
785                    LifetimeName::Infer => {
786                        // If the user writes `'_`, we use the *ordinary* elision
787                        // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
788                        // resolved the same as the `'_` in `&'_ Foo`.
789                        //
790                        // cc #48468
791                    }
792                    LifetimeName::Param(..) | LifetimeName::Static => {
793                        // If the user wrote an explicit name, use that.
794                        self.visit_lifetime(&*lifetime);
795                    }
796                    LifetimeName::Error => {}
797                }
798            }
799            hir::TyKind::Ref(lifetime_ref, ref mt) => {
800                self.visit_lifetime(lifetime_ref);
801                let scope = Scope::ObjectLifetimeDefault {
802                    lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
803                    s: self.scope,
804                };
805                self.with(scope, |this| this.visit_ty_unambig(mt.ty));
806            }
807            hir::TyKind::TraitAscription(bounds) => {
808                let scope = Scope::TraitRefBoundary { s: self.scope };
809                self.with(scope, |this| {
810                    let scope = Scope::LateBoundary {
811                        s: this.scope,
812                        what: "`impl Trait` in binding",
813                        deny_late_regions: true,
814                    };
815                    this.with(scope, |this| {
816                        for bound in bounds {
817                            this.visit_param_bound(bound);
818                        }
819                    })
820                });
821            }
822            _ => intravisit::walk_ty(self, ty),
823        }
824    }
825
826    #[instrument(level = "debug", skip(self))]
827    fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
828        intravisit::walk_ty_pat(self, p)
829    }
830
831    #[instrument(level = "debug", skip(self))]
832    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
833        use self::hir::TraitItemKind::*;
834        match trait_item.kind {
835            Fn(_, _) => {
836                self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
837                    intravisit::walk_trait_item(this, trait_item)
838                });
839            }
840            Type(bounds, ty) => {
841                self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
842                    this.visit_generics(trait_item.generics);
843                    for bound in bounds {
844                        this.visit_param_bound(bound);
845                    }
846                    if let Some(ty) = ty {
847                        this.visit_ty_unambig(ty);
848                    }
849                })
850            }
851            Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
852                intravisit::walk_trait_item(this, trait_item)
853            }),
854        }
855    }
856
857    #[instrument(level = "debug", skip(self))]
858    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
859        use self::hir::ImplItemKind::*;
860        match impl_item.kind {
861            Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
862                intravisit::walk_impl_item(this, impl_item)
863            }),
864            Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
865                this.visit_generics(impl_item.generics);
866                this.visit_ty_unambig(ty);
867            }),
868            Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
869                intravisit::walk_impl_item(this, impl_item)
870            }),
871        }
872    }
873
874    #[instrument(level = "debug", skip(self))]
875    fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
876        match lifetime_ref.res {
877            hir::LifetimeName::Static => {
878                self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
879            }
880            hir::LifetimeName::Param(param_def_id) => {
881                self.resolve_lifetime_ref(param_def_id, lifetime_ref)
882            }
883            // If we've already reported an error, just ignore `lifetime_ref`.
884            hir::LifetimeName::Error => {}
885            // Those will be resolved by typechecking.
886            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
887        }
888    }
889
890    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
891        for (i, segment) in path.segments.iter().enumerate() {
892            let depth = path.segments.len() - i - 1;
893            if let Some(args) = segment.args {
894                self.visit_segment_args(path.res, depth, args);
895            }
896        }
897        if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
898            self.resolve_type_ref(param_def_id.expect_local(), hir_id);
899        }
900    }
901
902    fn visit_fn(
903        &mut self,
904        fk: intravisit::FnKind<'tcx>,
905        fd: &'tcx hir::FnDecl<'tcx>,
906        body_id: hir::BodyId,
907        _: Span,
908        def_id: LocalDefId,
909    ) {
910        let output = match fd.output {
911            hir::FnRetTy::DefaultReturn(_) => None,
912            hir::FnRetTy::Return(ty) => Some(ty),
913        };
914        if let Some(ty) = output
915            && let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
916        {
917            let bound_vars: Vec<_> =
918                self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
919            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
920            self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
921        }
922        self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
923        intravisit::walk_fn_kind(self, fk);
924        self.visit_nested_body(body_id)
925    }
926
927    fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
928        let scope = Scope::TraitRefBoundary { s: self.scope };
929        self.with(scope, |this| {
930            walk_list!(this, visit_generic_param, generics.params);
931            walk_list!(this, visit_where_predicate, generics.predicates);
932        })
933    }
934
935    fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
936        let hir_id = predicate.hir_id;
937        match predicate.kind {
938            &hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
939                bounded_ty,
940                bounds,
941                bound_generic_params,
942                origin,
943                ..
944            }) => {
945                let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
946                    bound_generic_params
947                        .iter()
948                        .enumerate()
949                        .map(|(late_bound_idx, param)| {
950                            (
951                                (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
952                                late_arg_as_bound_arg(self.tcx, param),
953                            )
954                        })
955                        .unzip();
956
957                self.record_late_bound_vars(hir_id, binders);
958
959                // If this is an RTN type in the self type, then append those to the binder.
960                self.try_append_return_type_notation_params(hir_id, bounded_ty);
961
962                // Even if there are no lifetimes defined here, we still wrap it in a binder
963                // scope. If there happens to be a nested poly trait ref (an error), that
964                // will be `Concatenating` anyways, so we don't have to worry about the depth
965                // being wrong.
966                let scope = Scope::Binder {
967                    hir_id,
968                    bound_vars,
969                    s: self.scope,
970                    scope_type: BinderScopeType::Normal,
971                    where_bound_origin: Some(origin),
972                };
973                self.with(scope, |this| {
974                    walk_list!(this, visit_generic_param, bound_generic_params);
975                    this.visit_ty_unambig(bounded_ty);
976                    walk_list!(this, visit_param_bound, bounds);
977                })
978            }
979            &hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
980                lifetime,
981                bounds,
982                ..
983            }) => {
984                self.visit_lifetime(lifetime);
985                walk_list!(self, visit_param_bound, bounds);
986            }
987            &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
988                lhs_ty, rhs_ty, ..
989            }) => {
990                self.visit_ty_unambig(lhs_ty);
991                self.visit_ty_unambig(rhs_ty);
992            }
993        }
994    }
995
996    fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
997        self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
998    }
999
1000    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
1001        self.with(
1002            Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
1003            |this| {
1004                intravisit::walk_anon_const(this, c);
1005            },
1006        );
1007    }
1008
1009    fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
1010        match p.kind {
1011            GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1012                self.resolve_type_ref(p.def_id, p.hir_id);
1013            }
1014            GenericParamKind::Lifetime { .. } => {
1015                // No need to resolve lifetime params, we don't use them for things
1016                // like implicit `?Sized` or const-param-has-ty predicates.
1017            }
1018        }
1019
1020        match p.kind {
1021            GenericParamKind::Lifetime { .. } => {}
1022            GenericParamKind::Type { default, .. } => {
1023                if let Some(ty) = default {
1024                    self.visit_ty_unambig(ty);
1025                }
1026            }
1027            GenericParamKind::Const { ty, default, .. } => {
1028                self.visit_ty_unambig(ty);
1029                if let Some(default) = default {
1030                    self.visit_const_arg_unambig(default);
1031                }
1032            }
1033        }
1034    }
1035}
1036
1037fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
1038    debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
1039    let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(param_def_id) else {
1040        bug!("expected GenericParam for object_lifetime_default");
1041    };
1042    match param.source {
1043        hir::GenericParamSource::Generics => {
1044            let parent_def_id = tcx.local_parent(param_def_id);
1045            let generics = tcx.hir_get_generics(parent_def_id).unwrap();
1046            let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1047            let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1048
1049            // Scan the bounds and where-clauses on parameters to extract bounds
1050            // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1051            // for each type parameter.
1052            match param.kind {
1053                GenericParamKind::Type { .. } => {
1054                    let mut set = Set1::Empty;
1055
1056                    // Look for `type: ...` where clauses.
1057                    for bound in generics.bounds_for_param(param_def_id) {
1058                        // Ignore `for<'a> type: ...` as they can change what
1059                        // lifetimes mean (although we could "just" handle it).
1060                        if !bound.bound_generic_params.is_empty() {
1061                            continue;
1062                        }
1063
1064                        for bound in bound.bounds {
1065                            if let hir::GenericBound::Outlives(lifetime) = bound {
1066                                set.insert(lifetime.res);
1067                            }
1068                        }
1069                    }
1070
1071                    match set {
1072                        Set1::Empty => ObjectLifetimeDefault::Empty,
1073                        Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1074                        Set1::One(hir::LifetimeName::Param(param_def_id)) => {
1075                            ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1076                        }
1077                        _ => ObjectLifetimeDefault::Ambiguous,
1078                    }
1079                }
1080                _ => {
1081                    bug!("object_lifetime_default_raw must only be called on a type parameter")
1082                }
1083            }
1084        }
1085        hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
1086    }
1087}
1088
1089impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1090    fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1091    where
1092        F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
1093    {
1094        let BoundVarContext { tcx, rbv, .. } = self;
1095        let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
1096        let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
1097        {
1098            let _enter = span.enter();
1099            f(&mut this);
1100        }
1101    }
1102
1103    fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
1104        if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
1105            bug!(
1106                "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1107                self.rbv.late_bound_vars[&hir_id.local_id]
1108            )
1109        }
1110    }
1111
1112    /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1113    ///
1114    /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1115    /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1116    /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1117    ///
1118    /// For example:
1119    ///
1120    ///    fn foo<'a,'b,'c,T:Trait<'b>>(...)
1121    ///
1122    /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1123    /// lifetimes may be interspersed together.
1124    ///
1125    /// If early bound lifetimes are present, we separate them into their own list (and likewise
1126    /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1127    /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1128    /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1129    /// ordering is not important there.
1130    fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1131    where
1132        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1133    {
1134        let mut named_late_bound_vars = 0;
1135        let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
1136            .params
1137            .iter()
1138            .map(|param| {
1139                (
1140                    param.def_id,
1141                    match param.kind {
1142                        GenericParamKind::Lifetime { .. } => {
1143                            if self.tcx.is_late_bound(param.hir_id) {
1144                                let late_bound_idx = named_late_bound_vars;
1145                                named_late_bound_vars += 1;
1146                                ResolvedArg::late(late_bound_idx, param)
1147                            } else {
1148                                ResolvedArg::early(param)
1149                            }
1150                        }
1151                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1152                            ResolvedArg::early(param)
1153                        }
1154                    },
1155                )
1156            })
1157            .collect();
1158
1159        let binders: Vec<_> = generics
1160            .params
1161            .iter()
1162            .filter(|param| {
1163                matches!(param.kind, GenericParamKind::Lifetime { .. })
1164                    && self.tcx.is_late_bound(param.hir_id)
1165            })
1166            .map(|param| late_arg_as_bound_arg(self.tcx, param))
1167            .collect();
1168        self.record_late_bound_vars(hir_id, binders);
1169        let scope = Scope::Binder {
1170            hir_id,
1171            bound_vars,
1172            s: self.scope,
1173            scope_type: BinderScopeType::Normal,
1174            where_bound_origin: None,
1175        };
1176        self.with(scope, walk);
1177    }
1178
1179    fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1180    where
1181        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1182    {
1183        let bound_vars =
1184            generics.params.iter().map(|param| (param.def_id, ResolvedArg::early(param))).collect();
1185        self.record_late_bound_vars(hir_id, vec![]);
1186        let scope = Scope::Binder {
1187            hir_id,
1188            bound_vars,
1189            s: self.scope,
1190            scope_type: BinderScopeType::Normal,
1191            where_bound_origin: None,
1192        };
1193        self.with(scope, |this| {
1194            let scope = Scope::TraitRefBoundary { s: this.scope };
1195            this.with(scope, walk)
1196        });
1197    }
1198
1199    #[instrument(level = "debug", skip(self))]
1200    fn resolve_lifetime_ref(
1201        &mut self,
1202        region_def_id: LocalDefId,
1203        lifetime_ref: &'tcx hir::Lifetime,
1204    ) {
1205        // Walk up the scope chain, tracking the number of fn scopes
1206        // that we pass through, until we find a lifetime with the
1207        // given name or we run out of scopes.
1208        // search.
1209        let mut late_depth = 0;
1210        let mut scope = self.scope;
1211        let mut outermost_body = None;
1212        let mut crossed_late_boundary = None;
1213        let mut opaque_capture_scopes = vec![];
1214        let result = loop {
1215            match *scope {
1216                Scope::Body { id, s } => {
1217                    outermost_body = Some(id);
1218                    scope = s;
1219                }
1220
1221                Scope::Root { opt_parent_item } => {
1222                    if let Some(parent_item) = opt_parent_item
1223                        && let parent_generics = self.tcx.generics_of(parent_item)
1224                        && parent_generics
1225                            .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
1226                            .is_some()
1227                    {
1228                        break Some(ResolvedArg::EarlyBound(region_def_id));
1229                    }
1230                    break None;
1231                }
1232
1233                Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1234                    if let Some(&def) = bound_vars.get(&region_def_id) {
1235                        break Some(def.shifted(late_depth));
1236                    }
1237                    match scope_type {
1238                        BinderScopeType::Normal => late_depth += 1,
1239                        BinderScopeType::Concatenating => {}
1240                    }
1241                    // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
1242                    // regular fns.
1243                    if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1244                        && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
1245                        && let Some(generics) =
1246                            self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
1247                        && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1248                        && param.is_elided_lifetime()
1249                        && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
1250                        && !self.tcx.features().anonymous_lifetime_in_impl_trait()
1251                    {
1252                        let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
1253                            &self.tcx.sess,
1254                            sym::anonymous_lifetime_in_impl_trait,
1255                            lifetime_ref.ident.span,
1256                            "anonymous lifetimes in `impl Trait` are unstable",
1257                        );
1258
1259                        if let Some(generics) =
1260                            self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
1261                        {
1262                            let new_param_sugg =
1263                                if let Some(span) = generics.span_for_lifetime_suggestion() {
1264                                    (span, "'a, ".to_owned())
1265                                } else {
1266                                    (generics.span, "<'a>".to_owned())
1267                                };
1268
1269                            let lifetime_sugg = lifetime_ref.suggestion("'a");
1270                            let suggestions = vec![lifetime_sugg, new_param_sugg];
1271
1272                            diag.span_label(
1273                                lifetime_ref.ident.span,
1274                                "expected named lifetime parameter",
1275                            );
1276                            diag.multipart_suggestion(
1277                                "consider introducing a named lifetime parameter",
1278                                suggestions,
1279                                rustc_errors::Applicability::MaybeIncorrect,
1280                            );
1281                        }
1282
1283                        diag.emit();
1284                        return;
1285                    }
1286                    scope = s;
1287                }
1288
1289                Scope::Opaque { captures, def_id, s } => {
1290                    opaque_capture_scopes.push((def_id, captures));
1291                    late_depth = 0;
1292                    scope = s;
1293                }
1294
1295                Scope::ObjectLifetimeDefault { s, .. }
1296                | Scope::Supertrait { s, .. }
1297                | Scope::TraitRefBoundary { s, .. } => {
1298                    scope = s;
1299                }
1300
1301                Scope::LateBoundary { s, what, deny_late_regions } => {
1302                    if deny_late_regions {
1303                        crossed_late_boundary = Some(what);
1304                    }
1305                    scope = s;
1306                }
1307            }
1308        };
1309
1310        if let Some(mut def) = result {
1311            def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
1312
1313            if let ResolvedArg::EarlyBound(..) = def {
1314                // Do not free early-bound regions, only late-bound ones.
1315            } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
1316                && let Some(what) = crossed_late_boundary
1317            {
1318                let use_span = lifetime_ref.ident.span;
1319                let def_span = self.tcx.def_span(param_def_id);
1320                let guar = match self.tcx.def_kind(param_def_id) {
1321                    DefKind::LifetimeParam => {
1322                        self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Lifetime {
1323                            use_span,
1324                            def_span,
1325                            what,
1326                        })
1327                    }
1328                    kind => span_bug!(
1329                        use_span,
1330                        "did not expect to resolve lifetime to {}",
1331                        kind.descr(param_def_id.to_def_id())
1332                    ),
1333                };
1334                def = ResolvedArg::Error(guar);
1335            } else if let Some(body_id) = outermost_body {
1336                let fn_id = self.tcx.hir_body_owner(body_id);
1337                match self.tcx.hir_node(fn_id) {
1338                    Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
1339                    | Node::TraitItem(hir::TraitItem {
1340                        owner_id,
1341                        kind: hir::TraitItemKind::Fn(..),
1342                        ..
1343                    })
1344                    | Node::ImplItem(hir::ImplItem {
1345                        owner_id,
1346                        kind: hir::ImplItemKind::Fn(..),
1347                        ..
1348                    }) => {
1349                        def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
1350                    }
1351                    Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1352                        def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
1353                    }
1354                    _ => {}
1355                }
1356            }
1357
1358            self.insert_lifetime(lifetime_ref, def);
1359            return;
1360        }
1361
1362        // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
1363        // AST-based resolution does not care for impl-trait desugaring, which are the
1364        // responsibility of lowering. This may create a mismatch between the resolution
1365        // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1366        // ```
1367        // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1368        // ```
1369        //
1370        // In such case, walk back the binders to diagnose it properly.
1371        let mut scope = self.scope;
1372        loop {
1373            match *scope {
1374                Scope::Binder {
1375                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1376                } => {
1377                    self.tcx.dcx().emit_err(errors::LateBoundInApit::Lifetime {
1378                        span: lifetime_ref.ident.span,
1379                        param_span: self.tcx.def_span(region_def_id),
1380                    });
1381                    return;
1382                }
1383                Scope::Root { .. } => break,
1384                Scope::Binder { s, .. }
1385                | Scope::Body { s, .. }
1386                | Scope::Opaque { s, .. }
1387                | Scope::ObjectLifetimeDefault { s, .. }
1388                | Scope::Supertrait { s, .. }
1389                | Scope::TraitRefBoundary { s, .. }
1390                | Scope::LateBoundary { s, .. } => {
1391                    scope = s;
1392                }
1393            }
1394        }
1395
1396        self.tcx.dcx().span_delayed_bug(
1397            lifetime_ref.ident.span,
1398            format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1399        );
1400    }
1401
1402    /// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
1403    /// and ban them. Type variables instantiated inside binders aren't
1404    /// well-supported at the moment, so this doesn't work.
1405    /// In the future, this should be fixed and this error should be removed.
1406    fn check_lifetime_is_capturable(
1407        &self,
1408        opaque_def_id: LocalDefId,
1409        lifetime: ResolvedArg,
1410        capture_span: Span,
1411    ) -> Result<(), ErrorGuaranteed> {
1412        let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
1413        let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
1414        let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
1415            // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
1416            // it must be a reified late-bound lifetime from a trait goal.
1417            hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
1418            // Other items are fine.
1419            hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
1420            hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
1421                "higher-ranked lifetime from function pointer"
1422            }
1423            hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
1424                "higher-ranked lifetime from `dyn` type"
1425            }
1426            _ => "higher-ranked lifetime",
1427        };
1428
1429        let decl_span = self.tcx.def_span(lifetime_def_id);
1430        let (span, label) = if capture_span != decl_span {
1431            (capture_span, None)
1432        } else {
1433            let opaque_span = self.tcx.def_span(opaque_def_id);
1434            (opaque_span, Some(opaque_span))
1435        };
1436
1437        // Ensure that the parent of the def is an item, not HRTB
1438        let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
1439            span,
1440            label,
1441            decl_span,
1442            bad_place,
1443        });
1444        Err(guar)
1445    }
1446
1447    #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
1448    fn remap_opaque_captures(
1449        &self,
1450        opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
1451        mut lifetime: ResolvedArg,
1452        ident: Ident,
1453    ) -> ResolvedArg {
1454        if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
1455            if let Err(guar) =
1456                self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
1457            {
1458                lifetime = ResolvedArg::Error(guar);
1459            }
1460        }
1461
1462        for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
1463            let mut captures = captures.borrow_mut();
1464            let remapped = *captures.entry(lifetime).or_insert_with(|| {
1465                let feed =
1466                    self.tcx.create_def(opaque_def_id, Some(ident.name), DefKind::LifetimeParam);
1467                feed.def_span(ident.span);
1468                feed.def_ident_span(Some(ident.span));
1469                feed.def_id()
1470            });
1471            lifetime = ResolvedArg::EarlyBound(remapped);
1472        }
1473        lifetime
1474    }
1475
1476    fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
1477        // Walk up the scope chain, tracking the number of fn scopes
1478        // that we pass through, until we find a lifetime with the
1479        // given name or we run out of scopes.
1480        // search.
1481        let mut late_depth = 0;
1482        let mut scope = self.scope;
1483        let mut crossed_late_boundary = None;
1484
1485        let result = loop {
1486            match *scope {
1487                Scope::Body { s, .. } => {
1488                    scope = s;
1489                }
1490
1491                Scope::Root { opt_parent_item } => {
1492                    if let Some(parent_item) = opt_parent_item
1493                        && let parent_generics = self.tcx.generics_of(parent_item)
1494                        && parent_generics
1495                            .param_def_id_to_index(self.tcx, param_def_id.to_def_id())
1496                            .is_some()
1497                    {
1498                        break Some(ResolvedArg::EarlyBound(param_def_id));
1499                    }
1500                    break None;
1501                }
1502
1503                Scope::Binder { ref bound_vars, scope_type, s, .. } => {
1504                    if let Some(&def) = bound_vars.get(&param_def_id) {
1505                        break Some(def.shifted(late_depth));
1506                    }
1507                    match scope_type {
1508                        BinderScopeType::Normal => late_depth += 1,
1509                        BinderScopeType::Concatenating => {}
1510                    }
1511                    scope = s;
1512                }
1513
1514                Scope::ObjectLifetimeDefault { s, .. }
1515                | Scope::Opaque { s, .. }
1516                | Scope::Supertrait { s, .. }
1517                | Scope::TraitRefBoundary { s, .. } => {
1518                    scope = s;
1519                }
1520
1521                Scope::LateBoundary { s, what, deny_late_regions: _ } => {
1522                    crossed_late_boundary = Some(what);
1523                    scope = s;
1524                }
1525            }
1526        };
1527
1528        if let Some(def) = result {
1529            if let ResolvedArg::LateBound(..) = def
1530                && let Some(what) = crossed_late_boundary
1531            {
1532                let use_span = self.tcx.hir().span(hir_id);
1533                let def_span = self.tcx.def_span(param_def_id);
1534                let guar = match self.tcx.def_kind(param_def_id) {
1535                    DefKind::ConstParam => {
1536                        self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Const {
1537                            use_span,
1538                            def_span,
1539                            what,
1540                        })
1541                    }
1542                    DefKind::TyParam => {
1543                        self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Type {
1544                            use_span,
1545                            def_span,
1546                            what,
1547                        })
1548                    }
1549                    kind => span_bug!(
1550                        use_span,
1551                        "did not expect to resolve non-lifetime param to {}",
1552                        kind.descr(param_def_id.to_def_id())
1553                    ),
1554                };
1555                self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1556            } else {
1557                self.rbv.defs.insert(hir_id.local_id, def);
1558            }
1559            return;
1560        }
1561
1562        // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
1563        // AST-based resolution does not care for impl-trait desugaring, which are the
1564        // responsibility of lowering. This may create a mismatch between the resolution
1565        // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
1566        // ```
1567        // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
1568        // ```
1569        //
1570        // In such case, walk back the binders to diagnose it properly.
1571        let mut scope = self.scope;
1572        loop {
1573            match *scope {
1574                Scope::Binder {
1575                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1576                } => {
1577                    let guar = self.tcx.dcx().emit_err(match self.tcx.def_kind(param_def_id) {
1578                        DefKind::TyParam => errors::LateBoundInApit::Type {
1579                            span: self.tcx.hir().span(hir_id),
1580                            param_span: self.tcx.def_span(param_def_id),
1581                        },
1582                        DefKind::ConstParam => errors::LateBoundInApit::Const {
1583                            span: self.tcx.hir().span(hir_id),
1584                            param_span: self.tcx.def_span(param_def_id),
1585                        },
1586                        kind => {
1587                            bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1588                        }
1589                    });
1590                    self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1591                    return;
1592                }
1593                Scope::Root { .. } => break,
1594                Scope::Binder { s, .. }
1595                | Scope::Body { s, .. }
1596                | Scope::Opaque { s, .. }
1597                | Scope::ObjectLifetimeDefault { s, .. }
1598                | Scope::Supertrait { s, .. }
1599                | Scope::TraitRefBoundary { s, .. }
1600                | Scope::LateBoundary { s, .. } => {
1601                    scope = s;
1602                }
1603            }
1604        }
1605
1606        self.tcx
1607            .dcx()
1608            .span_bug(self.tcx.hir().span(hir_id), format!("could not resolve {param_def_id:?}"));
1609    }
1610
1611    #[instrument(level = "debug", skip(self))]
1612    fn visit_segment_args(
1613        &mut self,
1614        res: Res,
1615        depth: usize,
1616        generic_args: &'tcx hir::GenericArgs<'tcx>,
1617    ) {
1618        if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
1619            self.visit_fn_like_elision(inputs, Some(output), false);
1620            return;
1621        }
1622
1623        for arg in generic_args.args {
1624            if let hir::GenericArg::Lifetime(lt) = arg {
1625                self.visit_lifetime(lt);
1626            }
1627        }
1628
1629        // Figure out if this is a type/trait segment,
1630        // which requires object lifetime defaults.
1631        let type_def_id = match res {
1632            Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1633            Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1634            Res::Def(
1635                DefKind::Struct
1636                | DefKind::Union
1637                | DefKind::Enum
1638                | DefKind::TyAlias
1639                | DefKind::Trait,
1640                def_id,
1641            ) if depth == 0 => Some(def_id),
1642            _ => None,
1643        };
1644
1645        debug!(?type_def_id);
1646
1647        // Compute a vector of defaults, one for each type parameter,
1648        // per the rules given in RFCs 599 and 1156. Example:
1649        //
1650        // ```rust
1651        // struct Foo<'a, T: 'a, U> { }
1652        // ```
1653        //
1654        // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1655        // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1656        // and `dyn Baz` to `dyn Baz + 'static` (because there is no
1657        // such bound).
1658        //
1659        // Therefore, we would compute `object_lifetime_defaults` to a
1660        // vector like `['x, 'static]`. Note that the vector only
1661        // includes type parameters.
1662        let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1663            let in_body = {
1664                let mut scope = self.scope;
1665                loop {
1666                    match *scope {
1667                        Scope::Root { .. } => break false,
1668
1669                        Scope::Body { .. } => break true,
1670
1671                        Scope::Binder { s, .. }
1672                        | Scope::ObjectLifetimeDefault { s, .. }
1673                        | Scope::Opaque { s, .. }
1674                        | Scope::Supertrait { s, .. }
1675                        | Scope::TraitRefBoundary { s, .. }
1676                        | Scope::LateBoundary { s, .. } => {
1677                            scope = s;
1678                        }
1679                    }
1680                }
1681            };
1682
1683            let rbv = &self.rbv;
1684            let generics = self.tcx.generics_of(def_id);
1685
1686            // `type_def_id` points to an item, so there is nothing to inherit generics from.
1687            debug_assert_eq!(generics.parent_count, 0);
1688
1689            let set_to_region = |set: ObjectLifetimeDefault| match set {
1690                ObjectLifetimeDefault::Empty => {
1691                    if in_body {
1692                        None
1693                    } else {
1694                        Some(ResolvedArg::StaticLifetime)
1695                    }
1696                }
1697                ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
1698                ObjectLifetimeDefault::Param(param_def_id) => {
1699                    // This index can be used with `generic_args` since `parent_count == 0`.
1700                    let index = generics.param_def_id_to_index[&param_def_id] as usize;
1701                    generic_args.args.get(index).and_then(|arg| match arg {
1702                        GenericArg::Lifetime(lt) => rbv.defs.get(&lt.hir_id.local_id).copied(),
1703                        _ => None,
1704                    })
1705                }
1706                ObjectLifetimeDefault::Ambiguous => None,
1707            };
1708            generics
1709                .own_params
1710                .iter()
1711                .filter_map(|param| {
1712                    match self.tcx.def_kind(param.def_id) {
1713                        // Generic consts don't impose any constraints.
1714                        //
1715                        // We still store a dummy value here to allow generic parameters
1716                        // in an arbitrary order.
1717                        DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1718                        DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1719                        // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
1720                        // works. Ignore it because it can't have a meaningful lifetime default.
1721                        DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1722                        dk => bug!("unexpected def_kind {:?}", dk),
1723                    }
1724                })
1725                .map(set_to_region)
1726                .collect()
1727        });
1728
1729        debug!(?object_lifetime_defaults);
1730
1731        let mut i = 0;
1732        for arg in generic_args.args {
1733            match arg {
1734                GenericArg::Lifetime(_) => {}
1735                GenericArg::Type(ty) => {
1736                    if let Some(&lt) = object_lifetime_defaults.get(i) {
1737                        let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1738                        self.with(scope, |this| this.visit_ty(ty));
1739                    } else {
1740                        self.visit_ty(ty);
1741                    }
1742                    i += 1;
1743                }
1744                GenericArg::Const(ct) => {
1745                    self.visit_const_arg(ct);
1746                    i += 1;
1747                }
1748                GenericArg::Infer(inf) => {
1749                    self.visit_id(inf.hir_id);
1750                    i += 1;
1751                }
1752            }
1753        }
1754
1755        // Hack: When resolving the type `XX` in an assoc ty binding like
1756        // `dyn Foo<'b, Item = XX>`, the current object-lifetime default
1757        // would be to examine the trait `Foo` to check whether it has
1758        // a lifetime bound declared on `Item`. e.g., if `Foo` is
1759        // declared like so, then the default object lifetime bound in
1760        // `XX` should be `'b`:
1761        //
1762        // ```rust
1763        // trait Foo<'a> {
1764        //   type Item: 'a;
1765        // }
1766        // ```
1767        //
1768        // but if we just have `type Item;`, then it would be
1769        // `'static`. However, we don't get all of this logic correct.
1770        //
1771        // Instead, we do something hacky: if there are no lifetime parameters
1772        // to the trait, then we simply use a default object lifetime
1773        // bound of `'static`, because there is no other possibility. On the other hand,
1774        // if there ARE lifetime parameters, then we require the user to give an
1775        // explicit bound for now.
1776        //
1777        // This is intended to leave room for us to implement the
1778        // correct behavior in the future.
1779        let has_lifetime_parameter =
1780            generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1781
1782        // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
1783        // in the trait ref `YY<...>` in `Item: YY<...>`.
1784        for constraint in generic_args.constraints {
1785            let scope = Scope::ObjectLifetimeDefault {
1786                lifetime: if has_lifetime_parameter {
1787                    None
1788                } else {
1789                    Some(ResolvedArg::StaticLifetime)
1790                },
1791                s: self.scope,
1792            };
1793            // If the args are parenthesized, then this must be `feature(return_type_notation)`.
1794            // In that case, introduce a binder over all of the function's early and late bound vars.
1795            //
1796            // For example, given
1797            // ```
1798            // trait Foo {
1799            //     async fn x<'r, T>();
1800            // }
1801            // ```
1802            // and a bound that looks like:
1803            //    `for<'a> T::Trait<'a, x(..): for<'b> Other<'b>>`
1804            // this is going to expand to something like:
1805            //    `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
1806            if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
1807            {
1808                let bound_vars = if let Some(type_def_id) = type_def_id
1809                    && self.tcx.def_kind(type_def_id) == DefKind::Trait
1810                    && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
1811                        self.tcx,
1812                        type_def_id,
1813                        constraint.ident,
1814                        ty::AssocKind::Fn,
1815                    ) {
1816                    bound_vars.extend(
1817                        self.tcx
1818                            .generics_of(assoc_fn.def_id)
1819                            .own_params
1820                            .iter()
1821                            .map(|param| generic_param_def_as_bound_arg(param)),
1822                    );
1823                    bound_vars.extend(
1824                        self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars(),
1825                    );
1826                    bound_vars
1827                } else {
1828                    self.tcx
1829                        .dcx()
1830                        .span_delayed_bug(constraint.ident.span, "bad return type notation here");
1831                    vec![]
1832                };
1833                self.with(scope, |this| {
1834                    let scope = Scope::Supertrait { bound_vars, s: this.scope };
1835                    this.with(scope, |this| {
1836                        let (bound_vars, _) = this.poly_trait_ref_binder_info();
1837                        this.record_late_bound_vars(constraint.hir_id, bound_vars);
1838                        this.visit_assoc_item_constraint(constraint)
1839                    });
1840                });
1841            } else if let Some(type_def_id) = type_def_id {
1842                let bound_vars = BoundVarContext::supertrait_hrtb_vars(
1843                    self.tcx,
1844                    type_def_id,
1845                    constraint.ident,
1846                    ty::AssocKind::Type,
1847                )
1848                .map(|(bound_vars, _)| bound_vars);
1849                self.with(scope, |this| {
1850                    let scope = Scope::Supertrait {
1851                        bound_vars: bound_vars.unwrap_or_default(),
1852                        s: this.scope,
1853                    };
1854                    this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1855                });
1856            } else {
1857                self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1858            }
1859        }
1860    }
1861
1862    /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
1863    /// associated type name and starting trait.
1864    /// For example, imagine we have
1865    /// ```ignore (illustrative)
1866    /// trait Foo<'a, 'b> {
1867    ///   type As;
1868    /// }
1869    /// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
1870    /// trait Bar: for<'b> Bar<'b> {}
1871    /// ```
1872    /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
1873    /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
1874    fn supertrait_hrtb_vars(
1875        tcx: TyCtxt<'tcx>,
1876        def_id: DefId,
1877        assoc_name: Ident,
1878        assoc_kind: ty::AssocKind,
1879    ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
1880        let trait_defines_associated_item_named = |trait_def_id: DefId| {
1881            tcx.associated_items(trait_def_id).find_by_name_and_kind(
1882                tcx,
1883                assoc_name,
1884                assoc_kind,
1885                trait_def_id,
1886            )
1887        };
1888
1889        use smallvec::{SmallVec, smallvec};
1890        let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1891            smallvec![(def_id, smallvec![])];
1892        let mut visited: FxHashSet<DefId> = FxHashSet::default();
1893        loop {
1894            let Some((def_id, bound_vars)) = stack.pop() else {
1895                break None;
1896            };
1897            // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
1898            // there being no supertrait HRTBs.
1899            match tcx.def_kind(def_id) {
1900                DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
1901                _ => break None,
1902            }
1903
1904            if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
1905                break Some((bound_vars.into_iter().collect(), assoc_item));
1906            }
1907            let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_name));
1908            let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| {
1909                let bound_predicate = pred.kind();
1910                match bound_predicate.skip_binder() {
1911                    ty::ClauseKind::Trait(data) => {
1912                        // The order here needs to match what we would get from
1913                        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
1914                        let pred_bound_vars = bound_predicate.bound_vars();
1915                        let mut all_bound_vars = bound_vars.clone();
1916                        all_bound_vars.extend(pred_bound_vars.iter());
1917                        let super_def_id = data.trait_ref.def_id;
1918                        Some((super_def_id, all_bound_vars))
1919                    }
1920                    _ => None,
1921                }
1922            });
1923
1924            let obligations = obligations.filter(|o| visited.insert(o.0));
1925            stack.extend(obligations);
1926        }
1927    }
1928
1929    #[instrument(level = "debug", skip(self))]
1930    fn visit_fn_like_elision(
1931        &mut self,
1932        inputs: &'tcx [hir::Ty<'tcx>],
1933        output: Option<&'tcx hir::Ty<'tcx>>,
1934        in_closure: bool,
1935    ) {
1936        self.with(
1937            Scope::ObjectLifetimeDefault {
1938                lifetime: Some(ResolvedArg::StaticLifetime),
1939                s: self.scope,
1940            },
1941            |this| {
1942                for input in inputs {
1943                    this.visit_ty_unambig(input);
1944                }
1945                if !in_closure && let Some(output) = output {
1946                    this.visit_ty_unambig(output);
1947                }
1948            },
1949        );
1950        if in_closure && let Some(output) = output {
1951            self.visit_ty_unambig(output);
1952        }
1953    }
1954
1955    #[instrument(level = "debug", skip(self))]
1956    fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1957        let mut late_depth = 0;
1958        let mut scope = self.scope;
1959        let mut opaque_capture_scopes = vec![];
1960        let mut lifetime = loop {
1961            match *scope {
1962                Scope::Binder { s, scope_type, .. } => {
1963                    match scope_type {
1964                        BinderScopeType::Normal => late_depth += 1,
1965                        BinderScopeType::Concatenating => {}
1966                    }
1967                    scope = s;
1968                }
1969
1970                Scope::Root { .. } => break ResolvedArg::StaticLifetime,
1971
1972                Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1973
1974                Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
1975                    break l.shifted(late_depth);
1976                }
1977
1978                Scope::Opaque { captures, def_id, s } => {
1979                    opaque_capture_scopes.push((def_id, captures));
1980                    late_depth = 0;
1981                    scope = s;
1982                }
1983
1984                Scope::Supertrait { s, .. }
1985                | Scope::TraitRefBoundary { s, .. }
1986                | Scope::LateBoundary { s, .. } => {
1987                    scope = s;
1988                }
1989            }
1990        };
1991
1992        lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
1993
1994        self.insert_lifetime(lifetime_ref, lifetime);
1995    }
1996
1997    #[instrument(level = "debug", skip(self))]
1998    fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
1999        debug!(span = ?lifetime_ref.ident.span);
2000        self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
2001    }
2002
2003    // When we have a return type notation type in a where clause, like
2004    // `where <T as Trait>::method(..): Send`, we need to introduce new bound
2005    // vars to the existing where clause's binder, to represent the lifetimes
2006    // elided by the return-type-notation syntax.
2007    //
2008    // For example, given
2009    // ```
2010    // trait Foo {
2011    //     async fn x<'r>();
2012    // }
2013    // ```
2014    // and a bound that looks like:
2015    //    `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
2016    // this is going to expand to something like:
2017    //    `for<'a, 'b, 'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
2018    //
2019    // We handle this similarly for associated-type-bound style return-type-notation
2020    // in `visit_segment_args`.
2021    fn try_append_return_type_notation_params(
2022        &mut self,
2023        hir_id: HirId,
2024        hir_ty: &'tcx hir::Ty<'tcx>,
2025    ) {
2026        let hir::TyKind::Path(qpath) = hir_ty.kind else {
2027            // We only care about path types here. All other self types
2028            // (including nesting the RTN type in another type) don't do
2029            // anything.
2030            return;
2031        };
2032
2033        let (mut bound_vars, item_def_id, item_segment) = match qpath {
2034            // If we have a fully qualified method, then we don't need to do any special lookup.
2035            hir::QPath::Resolved(_, path)
2036                if let [.., item_segment] = &path.segments[..]
2037                    && item_segment.args.is_some_and(|args| {
2038                        matches!(
2039                            args.parenthesized,
2040                            hir::GenericArgsParentheses::ReturnTypeNotation
2041                        )
2042                    }) =>
2043            {
2044                match path.res {
2045                    Res::Err => return,
2046                    Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
2047                    _ => bug!("only expected method resolution for fully qualified RTN"),
2048                }
2049            }
2050
2051            // If we have a type-dependent path, then we do need to do some lookup.
2052            hir::QPath::TypeRelative(qself, item_segment)
2053                if item_segment.args.is_some_and(|args| {
2054                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2055                }) =>
2056            {
2057                // First, ignore a qself that isn't a type or `Self` param. Those are the
2058                // only ones that support `T::Assoc` anyways in HIR lowering.
2059                let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
2060                    return;
2061                };
2062                match path.res {
2063                    Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
2064                        let mut bounds =
2065                            self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
2066                                BoundVarContext::supertrait_hrtb_vars(
2067                                    self.tcx,
2068                                    trait_def_id,
2069                                    item_segment.ident,
2070                                    ty::AssocKind::Fn,
2071                                )
2072                            });
2073
2074                        let Some((bound_vars, assoc_item)) = bounds.next() else {
2075                            // This will error in HIR lowering.
2076                            self.tcx
2077                                .dcx()
2078                                .span_delayed_bug(path.span, "no resolution for RTN path");
2079                            return;
2080                        };
2081
2082                        // Don't bail if we have identical bounds, which may be collected from
2083                        // something like `T: Bound + Bound`, or via elaborating supertraits.
2084                        for (second_vars, second_assoc_item) in bounds {
2085                            if second_vars != bound_vars || second_assoc_item != assoc_item {
2086                                // This will error in HIR lowering.
2087                                self.tcx.dcx().span_delayed_bug(
2088                                    path.span,
2089                                    "ambiguous resolution for RTN path",
2090                                );
2091                                return;
2092                            }
2093                        }
2094
2095                        (bound_vars, assoc_item.def_id, item_segment)
2096                    }
2097                    // If we have a self type alias (in an impl), try to resolve an
2098                    // associated item from one of the supertraits of the impl's trait.
2099                    Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
2100                        let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self
2101                            .tcx
2102                            .hir_node_by_def_id(impl_def_id.expect_local())
2103                            .expect_item()
2104                            .kind
2105                        else {
2106                            return;
2107                        };
2108                        let Some(trait_def_id) = trait_ref.trait_def_id() else {
2109                            return;
2110                        };
2111                        let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
2112                            self.tcx,
2113                            trait_def_id,
2114                            item_segment.ident,
2115                            ty::AssocKind::Fn,
2116                        ) else {
2117                            return;
2118                        };
2119                        (bound_vars, assoc_item.def_id, item_segment)
2120                    }
2121                    _ => return,
2122                }
2123            }
2124
2125            _ => return,
2126        };
2127
2128        // Append the early-bound vars on the function, and then the late-bound ones.
2129        // We actually turn type parameters into higher-ranked types here, but we
2130        // deny them later in HIR lowering.
2131        bound_vars.extend(
2132            self.tcx
2133                .generics_of(item_def_id)
2134                .own_params
2135                .iter()
2136                .map(|param| generic_param_def_as_bound_arg(param)),
2137        );
2138        bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
2139
2140        // SUBTLE: Stash the old bound vars onto the *item segment* before appending
2141        // the new bound vars. We do this because we need to know how many bound vars
2142        // are present on the binder explicitly (i.e. not return-type-notation vars)
2143        // to do bound var shifting correctly in HIR lowering.
2144        //
2145        // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
2146        // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
2147        // parent) will include `'a` AND all the early- and late-bound vars of the
2148        // method. But when lowering the RTN type, we just want the list of vars
2149        // we used to resolve the trait ref. We explicitly stored those back onto
2150        // the item segment, since there's no other good place to put them.
2151        //
2152        // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
2153        // And this is exercised in:
2154        // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
2155        let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
2156        let existing_bound_vars_saved = existing_bound_vars.clone();
2157        existing_bound_vars.extend(bound_vars);
2158        self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
2159    }
2160
2161    /// Walk the generics of the item for a trait bound whose self type
2162    /// corresponds to the expected res, and return the trait def id.
2163    fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
2164        std::iter::from_coroutine(
2165            #[coroutine]
2166            move || {
2167                let mut scope = self.scope;
2168                loop {
2169                    let hir_id = match *scope {
2170                        Scope::Binder { hir_id, .. } => Some(hir_id),
2171                        Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2172                            Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2173                        }
2174                        Scope::Body { .. }
2175                        | Scope::ObjectLifetimeDefault { .. }
2176                        | Scope::Supertrait { .. }
2177                        | Scope::TraitRefBoundary { .. }
2178                        | Scope::LateBoundary { .. }
2179                        | Scope::Opaque { .. }
2180                        | Scope::Root { opt_parent_item: None } => None,
2181                    };
2182
2183                    if let Some(hir_id) = hir_id {
2184                        let node = self.tcx.hir_node(hir_id);
2185                        // If this is a `Self` bound in a trait, yield the trait itself.
2186                        // Specifically, we don't need to look at any supertraits since
2187                        // we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2188                        if let Res::SelfTyParam { trait_: _ } = expected_res
2189                            && let hir::Node::Item(item) = node
2190                            && let hir::ItemKind::Trait(..) = item.kind
2191                        {
2192                            // Yield the trait's def id. Supertraits will be
2193                            // elaborated from that.
2194                            yield item.owner_id.def_id.to_def_id();
2195                        } else if let Some(generics) = node.generics() {
2196                            for pred in generics.predicates {
2197                                let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
2198                                else {
2199                                    continue;
2200                                };
2201                                let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2202                                    pred.bounded_ty.kind
2203                                else {
2204                                    continue;
2205                                };
2206                                // Match the expected res.
2207                                if bounded_path.res != expected_res {
2208                                    continue;
2209                                }
2210                                for pred in pred.bounds {
2211                                    match pred {
2212                                        hir::GenericBound::Trait(poly_trait_ref) => {
2213                                            if let Some(def_id) =
2214                                                poly_trait_ref.trait_ref.trait_def_id()
2215                                            {
2216                                                yield def_id;
2217                                            }
2218                                        }
2219                                        hir::GenericBound::Outlives(_)
2220                                        | hir::GenericBound::Use(_, _) => {}
2221                                    }
2222                                }
2223                            }
2224                        }
2225                    }
2226
2227                    match *scope {
2228                        Scope::Binder { s, .. }
2229                        | Scope::Body { s, .. }
2230                        | Scope::ObjectLifetimeDefault { s, .. }
2231                        | Scope::Supertrait { s, .. }
2232                        | Scope::TraitRefBoundary { s }
2233                        | Scope::LateBoundary { s, .. }
2234                        | Scope::Opaque { s, .. } => {
2235                            scope = s;
2236                        }
2237                        Scope::Root { .. } => break,
2238                    }
2239                }
2240            },
2241        )
2242    }
2243}
2244
2245/// Detects late-bound lifetimes and inserts them into
2246/// `late_bound`.
2247///
2248/// A region declared on a fn is **late-bound** if:
2249/// - it is constrained by an argument type;
2250/// - it does not appear in a where-clause.
2251///
2252/// "Constrained" basically means that it appears in any type but
2253/// not amongst the inputs to a projection. In other words, `<&'a
2254/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
2255fn is_late_bound_map(
2256    tcx: TyCtxt<'_>,
2257    owner_id: hir::OwnerId,
2258) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2259    let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?;
2260    let generics = tcx.hir_get_generics(owner_id.def_id)?;
2261
2262    let mut late_bound = FxIndexSet::default();
2263
2264    let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2265    for arg_ty in sig.decl.inputs {
2266        constrained_by_input.visit_ty_unambig(arg_ty);
2267    }
2268
2269    let mut appears_in_output =
2270        AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
2271    intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2272    if appears_in_output.has_fully_capturing_opaque {
2273        appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2274    }
2275
2276    debug!(?constrained_by_input.regions);
2277
2278    // Walk the lifetimes that appear in where clauses.
2279    //
2280    // Subtle point: because we disallow nested bindings, we can just
2281    // ignore binders here and scrape up all names we see.
2282    let mut appears_in_where_clause =
2283        AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
2284    appears_in_where_clause.visit_generics(generics);
2285    debug!(?appears_in_where_clause.regions);
2286
2287    // Late bound regions are those that:
2288    // - appear in the inputs
2289    // - do not appear in the where-clauses
2290    // - are not implicitly captured by `impl Trait`
2291    for param in generics.params {
2292        match param.kind {
2293            hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
2294
2295            // Neither types nor consts are late-bound.
2296            hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2297        }
2298
2299        // appears in the where clauses? early-bound.
2300        if appears_in_where_clause.regions.contains(&param.def_id) {
2301            continue;
2302        }
2303
2304        // does not appear in the inputs, but appears in the return type? early-bound.
2305        if !constrained_by_input.regions.contains(&param.def_id)
2306            && appears_in_output.regions.contains(&param.def_id)
2307        {
2308            continue;
2309        }
2310
2311        debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2312
2313        let inserted = late_bound.insert(param.hir_id.local_id);
2314        assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2315    }
2316
2317    debug!(?late_bound);
2318    return Some(tcx.arena.alloc(late_bound));
2319
2320    /// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
2321    ///
2322    /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
2323    /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
2324    /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
2325    /// handles cycle detection as we go through the query system.
2326    ///
2327    /// This is necessary in the first place for the following case:
2328    /// ```rust,ignore (pseudo-Rust)
2329    /// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
2330    /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
2331    /// ```
2332    ///
2333    /// If we conservatively considered `'a` unconstrained then we could break users who had written code before
2334    /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
2335    /// causing an error during HIR ty lowering as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
2336    /// but appears in the output type `<() as Trait<'a>>::Assoc`.
2337    ///
2338    /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
2339    ///
2340    /// See #100508 #85533 #47511 for additional context
2341    struct ConstrainedCollectorPostHirTyLowering {
2342        arg_is_constrained: Box<[bool]>,
2343    }
2344
2345    use ty::Ty;
2346    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2347        fn visit_ty(&mut self, t: Ty<'tcx>) {
2348            match t.kind() {
2349                ty::Param(param_ty) => {
2350                    self.arg_is_constrained[param_ty.index as usize] = true;
2351                }
2352                ty::Alias(ty::Projection | ty::Inherent, _) => return,
2353                _ => (),
2354            }
2355            t.super_visit_with(self)
2356        }
2357
2358        fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2359
2360        fn visit_region(&mut self, r: ty::Region<'tcx>) {
2361            debug!("r={:?}", r.kind());
2362            if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2363                self.arg_is_constrained[region.index as usize] = true;
2364            }
2365        }
2366    }
2367
2368    struct ConstrainedCollector<'tcx> {
2369        tcx: TyCtxt<'tcx>,
2370        regions: FxHashSet<LocalDefId>,
2371    }
2372
2373    impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2374        fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2375            match ty.kind {
2376                hir::TyKind::Path(
2377                    hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2378                ) => {
2379                    // ignore lifetimes appearing in associated type
2380                    // projections, as they are not *constrained*
2381                    // (defined above)
2382                }
2383
2384                hir::TyKind::Path(hir::QPath::Resolved(
2385                    None,
2386                    hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2387                )) => {
2388                    // See comments on `ConstrainedCollectorPostHirTyLowering` for why this arm does not
2389                    // just consider args to be unconstrained.
2390                    let generics = self.tcx.generics_of(alias_def);
2391                    let mut walker = ConstrainedCollectorPostHirTyLowering {
2392                        arg_is_constrained: vec![false; generics.own_params.len()]
2393                            .into_boxed_slice(),
2394                    };
2395                    walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2396
2397                    match segments.last() {
2398                        Some(hir::PathSegment { args: Some(args), .. }) => {
2399                            let tcx = self.tcx;
2400                            for constrained_arg in
2401                                args.args.iter().enumerate().flat_map(|(n, arg)| {
2402                                    match walker.arg_is_constrained.get(n) {
2403                                        Some(true) => Some(arg),
2404                                        Some(false) => None,
2405                                        None => {
2406                                            tcx.dcx().span_delayed_bug(
2407                                                *span,
2408                                                format!(
2409                                                    "Incorrect generic arg count for alias {alias_def:?}"
2410                                                ),
2411                                            );
2412                                            None
2413                                        }
2414                                    }
2415                                })
2416                            {
2417                                self.visit_generic_arg(constrained_arg);
2418                            }
2419                        }
2420                        Some(_) => (),
2421                        None => bug!("Path with no segments or self type"),
2422                    }
2423                }
2424
2425                hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2426                    // consider only the lifetimes on the final
2427                    // segment; I am not sure it's even currently
2428                    // valid to have them elsewhere, but even if it
2429                    // is, those would be potentially inputs to
2430                    // projections
2431                    if let Some(last_segment) = path.segments.last() {
2432                        self.visit_path_segment(last_segment);
2433                    }
2434                }
2435
2436                _ => {
2437                    intravisit::walk_ty(self, ty);
2438                }
2439            }
2440        }
2441
2442        fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2443            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2444                self.regions.insert(def_id);
2445            }
2446        }
2447    }
2448
2449    struct AllCollector {
2450        has_fully_capturing_opaque: bool,
2451        regions: FxHashSet<LocalDefId>,
2452    }
2453
2454    impl<'tcx> Visitor<'tcx> for AllCollector {
2455        fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2456            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2457                self.regions.insert(def_id);
2458            }
2459        }
2460
2461        fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
2462            if !self.has_fully_capturing_opaque {
2463                self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
2464            }
2465            intravisit::walk_opaque_ty(self, opaque);
2466        }
2467    }
2468}
2469
2470fn deny_non_region_late_bound(
2471    tcx: TyCtxt<'_>,
2472    bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2473    where_: &str,
2474) {
2475    let mut first = true;
2476
2477    for (var, arg) in bound_vars {
2478        let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2479            span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2480        };
2481
2482        let what = match param.kind {
2483            hir::GenericParamKind::Type { .. } => "type",
2484            hir::GenericParamKind::Const { .. } => "const",
2485            hir::GenericParamKind::Lifetime { .. } => continue,
2486        };
2487
2488        let diag = tcx.dcx().struct_span_err(
2489            param.span,
2490            format!("late-bound {what} parameter not allowed on {where_}"),
2491        );
2492
2493        let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
2494
2495        first = false;
2496        *arg = ResolvedArg::Error(guar);
2497    }
2498}