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