rustc_hir_analysis/collect/
resolve_bound_vars.rs

1//! Resolution of early vs late bound lifetimes.
2//!
3//! Name resolution for lifetimes is performed on the AST and embedded into HIR. From this
4//! information, typechecking needs to transform the lifetime parameters into bound lifetimes.
5//! Lifetimes can be early-bound or late-bound. Construction of typechecking terms needs to visit
6//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
7//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
8
9use std::cell::RefCell;
10use std::fmt;
11use std::ops::ControlFlow;
12
13use rustc_ast::visit::walk_list;
14use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
15use rustc_errors::ErrorGuaranteed;
16use rustc_hir::def::{DefKind, Res};
17use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
18use rustc_hir::{
19    self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
20};
21use rustc_macros::extension;
22use rustc_middle::hir::nested_filter;
23use rustc_middle::middle::resolve_bound_vars::*;
24use rustc_middle::query::Providers;
25use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
26use rustc_middle::{bug, span_bug};
27use rustc_span::def_id::{DefId, LocalDefId};
28use rustc_span::{Ident, Span, sym};
29use tracing::{debug, debug_span, instrument};
30
31use crate::errors;
32
33#[extension(trait RegionExt)]
34impl ResolvedArg {
35    fn early(param: &GenericParam<'_>) -> ResolvedArg {
36        ResolvedArg::EarlyBound(param.def_id)
37    }
38
39    fn late(idx: u32, param: &GenericParam<'_>) -> ResolvedArg {
40        ResolvedArg::LateBound(ty::INNERMOST, idx, param.def_id)
41    }
42
43    fn id(&self) -> Option<LocalDefId> {
44        match *self {
45            ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
46
47            ResolvedArg::EarlyBound(id)
48            | ResolvedArg::LateBound(_, _, id)
49            | ResolvedArg::Free(_, id) => Some(id),
50        }
51    }
52
53    fn shifted(self, amount: u32) -> ResolvedArg {
54        match self {
55            ResolvedArg::LateBound(debruijn, idx, id) => {
56                ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
57            }
58            _ => self,
59        }
60    }
61}
62
63struct BoundVarContext<'a, 'tcx> {
64    tcx: TyCtxt<'tcx>,
65    rbv: &'a mut ResolveBoundVars,
66    scope: ScopeRef<'a>,
67}
68
69#[derive(Debug)]
70enum Scope<'a> {
71    /// Declares lifetimes, and each can be early-bound or late-bound.
72    /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and
73    /// it should be shifted by the number of `Binder`s in between the
74    /// declaration `Binder` and the location it's referenced from.
75    Binder {
76        /// We use an IndexMap here because we want these lifetimes in order
77        /// for diagnostics.
78        bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
79
80        scope_type: BinderScopeType,
81
82        /// The late bound vars for a given item are stored by `HirId` to be
83        /// queried later. However, if we enter an elision scope, we have to
84        /// later append the elided bound vars to the list and need to know what
85        /// to append to.
86        hir_id: HirId,
87
88        s: ScopeRef<'a>,
89
90        /// If this binder comes from a where clause, specify how it was created.
91        /// This is used to diagnose inaccessible lifetimes in APIT:
92        /// ```ignore (illustrative)
93        /// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
94        /// ```
95        where_bound_origin: Option<hir::PredicateOrigin>,
96    },
97
98    /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
99    /// if this is a fn body, otherwise the original definitions are used.
100    /// Unspecified lifetimes are inferred, unless an elision scope is nested,
101    /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`.
102    Body {
103        id: hir::BodyId,
104        s: ScopeRef<'a>,
105    },
106
107    /// Use a specific lifetime (if `Some`) or leave it unset (to be
108    /// inferred in a function body or potentially error outside one),
109    /// for the default choice of lifetime in a trait object type.
110    ObjectLifetimeDefault {
111        lifetime: Option<ResolvedArg>,
112        s: ScopeRef<'a>,
113    },
114
115    /// When we have nested trait refs, we concatenate late bound vars for inner
116    /// trait refs from outer ones. But we also need to include any HRTB
117    /// lifetimes encountered when identifying the trait that an associated type
118    /// is declared on.
119    Supertrait {
120        bound_vars: Vec<ty::BoundVariableKind>,
121        s: ScopeRef<'a>,
122    },
123
124    TraitRefBoundary {
125        s: ScopeRef<'a>,
126    },
127
128    /// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given:
129    /// `fn foo<'a>() -> impl MyTrait<'a> { ... }`
130    ///
131    /// HIR tells us that `'a` refer to the lifetime bound on `foo`.
132    /// However, typeck and borrowck for opaques work based on using a new generic type.
133    /// `type MyAnonTy<'b> = impl MyTrait<'b>;`
134    ///
135    /// This scope collects the mapping `'a -> 'b`.
136    Opaque {
137        /// The opaque type we are traversing.
138        def_id: LocalDefId,
139        /// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`.
140        captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
141
142        s: ScopeRef<'a>,
143    },
144
145    /// Disallows capturing late-bound vars from parent scopes.
146    ///
147    /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
148    /// since we don't do something more correct like replacing any captured
149    /// late-bound vars with early-bound params in the const's own generics.
150    LateBoundary {
151        s: ScopeRef<'a>,
152        what: &'static str,
153        deny_late_regions: bool,
154    },
155
156    Root {
157        opt_parent_item: Option<LocalDefId>,
158    },
159}
160
161impl<'a> Scope<'a> {
162    // A helper for debugging scopes without printing parent scopes
163    fn debug_truncated(&'a self) -> impl fmt::Debug + 'a {
164        fmt::from_fn(move |f| match self {
165            Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
166                .debug_struct("Binder")
167                .field("bound_vars", bound_vars)
168                .field("scope_type", scope_type)
169                .field("hir_id", hir_id)
170                .field("where_bound_origin", where_bound_origin)
171                .field("s", &"..")
172                .finish(),
173            Self::Opaque { captures, def_id, s: _ } => f
174                .debug_struct("Opaque")
175                .field("def_id", def_id)
176                .field("captures", &captures.borrow())
177                .field("s", &"..")
178                .finish(),
179            Self::Body { id, s: _ } => {
180                f.debug_struct("Body").field("id", id).field("s", &"..").finish()
181            }
182            Self::ObjectLifetimeDefault { lifetime, s: _ } => f
183                .debug_struct("ObjectLifetimeDefault")
184                .field("lifetime", lifetime)
185                .field("s", &"..")
186                .finish(),
187            Self::Supertrait { bound_vars, s: _ } => f
188                .debug_struct("Supertrait")
189                .field("bound_vars", bound_vars)
190                .field("s", &"..")
191                .finish(),
192            Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
193            Self::LateBoundary { s: _, what, deny_late_regions } => f
194                .debug_struct("LateBoundary")
195                .field("what", what)
196                .field("deny_late_regions", deny_late_regions)
197                .finish(),
198            Self::Root { opt_parent_item } => {
199                f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
200            }
201        })
202    }
203}
204
205#[derive(Copy, Clone, Debug)]
206enum BinderScopeType {
207    /// Any non-concatenating binder scopes.
208    Normal,
209    /// Within a syntactic trait ref, there may be multiple poly trait refs that
210    /// are nested (under the `associated_type_bounds` feature). The binders of
211    /// the inner poly trait refs are extended from the outer poly trait refs
212    /// and don't increase the late bound depth. If you had
213    /// `T: for<'a>  Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope
214    /// would be `Concatenating`. This also used in trait refs in where clauses
215    /// where we have two binders `for<> T: for<> Foo` (I've intentionally left
216    /// out any lifetimes because they aren't needed to show the two scopes).
217    /// The inner `for<>` has a scope of `Concatenating`.
218    Concatenating,
219}
220
221type ScopeRef<'a> = &'a Scope<'a>;
222
223pub(crate) fn provide(providers: &mut Providers) {
224    *providers = Providers {
225        resolve_bound_vars,
226
227        named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
228        is_late_bound_map,
229        object_lifetime_default,
230        late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
231        opaque_captured_lifetimes: |tcx, id| {
232            &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
233                .opaque_captured_lifetimes
234                .get(&id)
235                .map_or(&[][..], |x| &x[..])
236        },
237
238        ..*providers
239    };
240}
241
242/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
243/// You should not read the result of this query directly, but rather use
244/// `named_variable_map`, `late_bound_vars_map`, etc.
245#[instrument(level = "debug", skip(tcx))]
246fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
247    let mut rbv = ResolveBoundVars::default();
248    let mut visitor =
249        BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
250    match tcx.hir_owner_node(local_def_id) {
251        hir::OwnerNode::Item(item) => visitor.visit_item(item),
252        hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
253        hir::OwnerNode::TraitItem(item) => {
254            let scope =
255                Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
256            visitor.scope = &scope;
257            visitor.visit_trait_item(item)
258        }
259        hir::OwnerNode::ImplItem(item) => {
260            let scope =
261                Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
262            visitor.scope = &scope;
263            visitor.visit_impl_item(item)
264        }
265        hir::OwnerNode::Crate(_) => {}
266        hir::OwnerNode::Synthetic => unreachable!(),
267    }
268
269    debug!(?rbv.defs);
270    debug!(?rbv.late_bound_vars);
271    debug!(?rbv.opaque_captured_lifetimes);
272    rbv
273}
274
275fn late_arg_as_bound_arg<'tcx>(
276    tcx: TyCtxt<'tcx>,
277    param: &GenericParam<'tcx>,
278) -> ty::BoundVariableKind {
279    let def_id = param.def_id.to_def_id();
280    let name = tcx.item_name(def_id);
281    match param.kind {
282        GenericParamKind::Lifetime { .. } => {
283            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
284        }
285        GenericParamKind::Type { .. } => {
286            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name))
287        }
288        GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
289    }
290}
291
292/// Turn a [`ty::GenericParamDef`] into a bound arg. Generally, this should only
293/// be used when turning early-bound vars into late-bound vars when lowering
294/// return type notation.
295fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
296    match param.kind {
297        ty::GenericParamDefKind::Lifetime => {
298            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id, param.name))
299        }
300        ty::GenericParamDefKind::Type { .. } => {
301            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
302        }
303        ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
304    }
305}
306
307/// Whether this opaque always captures lifetimes in scope.
308/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
309/// is enabled. We don't check the span of the edition, since this is done
310/// on a per-opaque basis to account for nested opaques.
311fn opaque_captures_all_in_scope_lifetimes<'tcx>(
312    tcx: TyCtxt<'tcx>,
313    opaque: &'tcx hir::OpaqueTy<'tcx>,
314) -> bool {
315    match opaque.origin {
316        // if the opaque has the `use<...>` syntax, the user is telling us that they only want
317        // to account for those lifetimes, so do not try to be clever.
318        _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
319        hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
320        _ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
321            true
322        }
323        hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
324    }
325}
326
327impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
328    /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
329    fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
330        let mut scope = self.scope;
331        let mut supertrait_bound_vars = vec![];
332        loop {
333            match scope {
334                Scope::Body { .. } | Scope::Root { .. } => {
335                    break (vec![], BinderScopeType::Normal);
336                }
337
338                Scope::Opaque { s, .. }
339                | Scope::ObjectLifetimeDefault { s, .. }
340                | Scope::LateBoundary { s, .. } => {
341                    scope = s;
342                }
343
344                Scope::Supertrait { s, bound_vars } => {
345                    supertrait_bound_vars = bound_vars.clone();
346                    scope = s;
347                }
348
349                Scope::TraitRefBoundary { .. } => {
350                    // We should only see super trait lifetimes if there is a `Binder` above
351                    // though this may happen when we call `poly_trait_ref_binder_info` with
352                    // an (erroneous, #113423) associated return type bound in an impl header.
353                    if !supertrait_bound_vars.is_empty() {
354                        self.tcx.dcx().delayed_bug(format!(
355                            "found supertrait lifetimes without a binder to append \
356                                them to: {supertrait_bound_vars:?}"
357                        ));
358                    }
359                    break (vec![], BinderScopeType::Normal);
360                }
361
362                Scope::Binder { hir_id, .. } => {
363                    // Nested poly trait refs have the binders concatenated
364                    let mut full_binders =
365                        self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
366                    full_binders.extend(supertrait_bound_vars);
367                    break (full_binders, BinderScopeType::Concatenating);
368                }
369            }
370        }
371    }
372
373    fn visit_poly_trait_ref_inner(
374        &mut self,
375        trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
376        non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
377    ) {
378        debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
379
380        let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
381
382        let initial_bound_vars = binders.len() as u32;
383        let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
384        let binders_iter =
385            trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
386                let arg = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
387                bound_vars.insert(param.def_id, arg);
388                late_arg_as_bound_arg(self.tcx, param)
389            });
390        binders.extend(binders_iter);
391
392        if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
393            deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
394        }
395
396        debug!(?binders);
397        self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
398
399        // Always introduce a scope here, even if this is in a where clause and
400        // we introduced the binders around the bounded Ty. In that case, we
401        // just reuse the concatenation functionality also present in nested trait
402        // refs.
403        let scope = Scope::Binder {
404            hir_id: trait_ref.trait_ref.hir_ref_id,
405            bound_vars,
406            s: self.scope,
407            scope_type,
408            where_bound_origin: None,
409        };
410        self.with(scope, |this| {
411            walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
412            this.visit_trait_ref(&trait_ref.trait_ref);
413        });
414    }
415}
416
417enum NonLifetimeBinderAllowed {
418    Deny(&'static str),
419    Allow,
420}
421
422impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
423    type NestedFilter = nested_filter::OnlyBodies;
424
425    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
426        self.tcx
427    }
428
429    fn visit_nested_body(&mut self, body: hir::BodyId) {
430        let body = self.tcx.hir_body(body);
431        self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
432            this.visit_body(body);
433        });
434    }
435
436    fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
437        if let hir::ExprKind::Closure(hir::Closure {
438            binder, bound_generic_params, fn_decl, ..
439        }) = e.kind
440        {
441            if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
442                fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
443                    /// Look for `_` anywhere in the signature of a `for<> ||` closure.
444                    /// This is currently disallowed.
445                    struct FindInferInClosureWithBinder;
446                    impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
447                        type Result = ControlFlow<Span>;
448
449                        fn visit_infer(
450                            &mut self,
451                            _inf_id: HirId,
452                            inf_span: Span,
453                            _kind: InferKind<'v>,
454                        ) -> Self::Result {
455                            ControlFlow::Break(inf_span)
456                        }
457                    }
458                    FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value()
459                }
460
461                let infer_in_rt_sp = match fn_decl.output {
462                    hir::FnRetTy::DefaultReturn(sp) => Some(sp),
463                    hir::FnRetTy::Return(ty) => span_of_infer(ty),
464                };
465
466                let infer_spans = fn_decl
467                    .inputs
468                    .into_iter()
469                    .filter_map(span_of_infer)
470                    .chain(infer_in_rt_sp)
471                    .collect::<Vec<_>>();
472
473                if !infer_spans.is_empty() {
474                    self.tcx
475                        .dcx()
476                        .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
477                }
478            }
479
480            let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
481                bound_generic_params
482                    .iter()
483                    .enumerate()
484                    .map(|(late_bound_idx, param)| {
485                        (
486                            (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
487                            late_arg_as_bound_arg(self.tcx, param),
488                        )
489                    })
490                    .unzip();
491
492            deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
493
494            self.record_late_bound_vars(e.hir_id, binders);
495            let scope = Scope::Binder {
496                hir_id: e.hir_id,
497                bound_vars,
498                s: self.scope,
499                scope_type: BinderScopeType::Normal,
500                where_bound_origin: None,
501            };
502
503            self.with(scope, |this| {
504                // a closure has no bounds, so everything
505                // contained within is scoped within its binder.
506                intravisit::walk_expr(this, e)
507            });
508        } else {
509            intravisit::walk_expr(self, e)
510        }
511    }
512
513    /// Resolve the lifetimes inside the opaque type, and save them into
514    /// `opaque_captured_lifetimes`.
515    ///
516    /// This method has special handling for opaques that capture all lifetimes,
517    /// like async desugaring.
518    #[instrument(level = "debug", skip(self))]
519    fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
520        let captures = RefCell::new(FxIndexMap::default());
521
522        let capture_all_in_scope_lifetimes =
523            opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
524        if capture_all_in_scope_lifetimes {
525            let lifetime_ident = |def_id: LocalDefId| {
526                let name = self.tcx.item_name(def_id.to_def_id());
527                let span = self.tcx.def_span(def_id);
528                Ident::new(name, span)
529            };
530
531            // We list scopes outwards, this causes us to see lifetime parameters in reverse
532            // declaration order. In order to make it consistent with what `generics_of` might
533            // give, we will reverse the IndexMap after early captures.
534            let mut late_depth = 0;
535            let mut scope = self.scope;
536            let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
537            loop {
538                match *scope {
539                    Scope::Binder { ref bound_vars, scope_type, s, .. } => {
540                        for (&original_lifetime, &def) in bound_vars.iter().rev() {
541                            if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
542                                let def = def.shifted(late_depth);
543                                let ident = lifetime_ident(original_lifetime);
544                                self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
545                            }
546                        }
547                        match scope_type {
548                            BinderScopeType::Normal => late_depth += 1,
549                            BinderScopeType::Concatenating => {}
550                        }
551                        scope = s;
552                    }
553
554                    Scope::Root { mut opt_parent_item } => {
555                        while let Some(parent_item) = opt_parent_item {
556                            let parent_generics = self.tcx.generics_of(parent_item);
557                            for param in parent_generics.own_params.iter().rev() {
558                                if let ty::GenericParamDefKind::Lifetime = param.kind {
559                                    let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
560                                    let ident = lifetime_ident(param.def_id.expect_local());
561                                    self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
562                                }
563                            }
564                            opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
565                        }
566                        break;
567                    }
568
569                    Scope::Opaque { captures, def_id, s } => {
570                        opaque_capture_scopes.push((def_id, captures));
571                        late_depth = 0;
572                        scope = s;
573                    }
574
575                    Scope::Body { .. } => {
576                        bug!("{:?}", scope)
577                    }
578
579                    Scope::ObjectLifetimeDefault { s, .. }
580                    | Scope::Supertrait { s, .. }
581                    | Scope::TraitRefBoundary { s, .. }
582                    | Scope::LateBoundary { s, .. } => {
583                        scope = s;
584                    }
585                }
586            }
587            captures.borrow_mut().reverse();
588        }
589
590        let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
591        self.with(scope, |this| {
592            let scope = Scope::TraitRefBoundary { s: this.scope };
593            this.with(scope, |this| {
594                let scope = Scope::LateBoundary {
595                    s: this.scope,
596                    what: "nested `impl Trait`",
597                    // We can capture late-bound regions; we just don't duplicate
598                    // lifetime or const params, so we can't allow those.
599                    deny_late_regions: false,
600                };
601                this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
602            })
603        });
604
605        let captures = captures.into_inner().into_iter().collect();
606        debug!(?captures);
607        self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
608    }
609
610    #[instrument(level = "debug", skip(self))]
611    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
612        match &item.kind {
613            hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
614                if let Some(of_trait) = of_trait {
615                    self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
616                }
617            }
618            _ => {}
619        }
620        match item.kind {
621            hir::ItemKind::Fn { generics, .. } => {
622                self.visit_early_late(item.hir_id(), generics, |this| {
623                    intravisit::walk_item(this, item);
624                });
625            }
626
627            hir::ItemKind::ExternCrate(_)
628            | hir::ItemKind::Use(..)
629            | hir::ItemKind::Macro(..)
630            | hir::ItemKind::Mod(..)
631            | hir::ItemKind::ForeignMod { .. }
632            | hir::ItemKind::Static(..)
633            | hir::ItemKind::GlobalAsm(..) => {
634                // These sorts of items have no lifetime parameters at all.
635                intravisit::walk_item(self, item);
636            }
637            hir::ItemKind::TyAlias(_, generics)
638            | hir::ItemKind::Const(_, generics, _)
639            | hir::ItemKind::Enum(_, generics)
640            | hir::ItemKind::Struct(_, generics)
641            | hir::ItemKind::Union(_, generics)
642            | hir::ItemKind::Trait(_, _, generics, ..)
643            | hir::ItemKind::TraitAlias(generics, ..)
644            | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
645                // These kinds of items have only early-bound lifetime parameters.
646                self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
647            }
648        }
649    }
650
651    fn visit_precise_capturing_arg(
652        &mut self,
653        arg: &'tcx hir::PreciseCapturingArg<'tcx>,
654    ) -> Self::Result {
655        match *arg {
656            hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
657                LifetimeName::Param(def_id) => {
658                    self.resolve_lifetime_ref(def_id, lt);
659                }
660                LifetimeName::Error => {}
661                LifetimeName::ImplicitObjectLifetimeDefault
662                | LifetimeName::Infer
663                | LifetimeName::Static => {
664                    self.tcx.dcx().emit_err(errors::BadPreciseCapture {
665                        span: lt.ident.span,
666                        kind: "lifetime",
667                        found: format!("`{}`", lt.ident.name),
668                    });
669                }
670            },
671            hir::PreciseCapturingArg::Param(param) => match param.res {
672                Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
673                | Res::SelfTyParam { trait_: def_id } => {
674                    self.resolve_type_ref(def_id.expect_local(), param.hir_id);
675                }
676                Res::SelfTyAlias { alias_to, .. } => {
677                    self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
678                        span: param.ident.span,
679                        self_span: self.tcx.def_span(alias_to),
680                        what: self.tcx.def_descr(alias_to),
681                    });
682                }
683                res => {
684                    self.tcx.dcx().span_delayed_bug(
685                        param.ident.span,
686                        format!("expected type or const param, found {res:?}"),
687                    );
688                }
689            },
690        }
691    }
692
693    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
694        match item.kind {
695            hir::ForeignItemKind::Fn(_, _, generics) => {
696                self.visit_early_late(item.hir_id(), generics, |this| {
697                    intravisit::walk_foreign_item(this, item);
698                })
699            }
700            hir::ForeignItemKind::Static(..) => {
701                intravisit::walk_foreign_item(self, item);
702            }
703            hir::ForeignItemKind::Type => {
704                intravisit::walk_foreign_item(self, item);
705            }
706        }
707    }
708
709    #[instrument(level = "debug", skip(self))]
710    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
711        match ty.kind {
712            hir::TyKind::BareFn(c) => {
713                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
714                    .generic_params
715                    .iter()
716                    .enumerate()
717                    .map(|(late_bound_idx, param)| {
718                        (
719                            (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
720                            late_arg_as_bound_arg(self.tcx, param),
721                        )
722                    })
723                    .unzip();
724
725                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
726
727                self.record_late_bound_vars(ty.hir_id, binders);
728                let scope = Scope::Binder {
729                    hir_id: ty.hir_id,
730                    bound_vars,
731                    s: self.scope,
732                    scope_type: BinderScopeType::Normal,
733                    where_bound_origin: None,
734                };
735                self.with(scope, |this| {
736                    // a bare fn has no bounds, so everything
737                    // contained within is scoped within its binder.
738                    intravisit::walk_ty(this, ty);
739                });
740            }
741            hir::TyKind::UnsafeBinder(binder) => {
742                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
743                    binder
744                        .generic_params
745                        .iter()
746                        .enumerate()
747                        .map(|(late_bound_idx, param)| {
748                            (
749                                (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
750                                late_arg_as_bound_arg(self.tcx, param),
751                            )
752                        })
753                        .unzip();
754
755                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
756
757                self.record_late_bound_vars(ty.hir_id, binders);
758                let scope = Scope::Binder {
759                    hir_id: ty.hir_id,
760                    bound_vars,
761                    s: self.scope,
762                    scope_type: BinderScopeType::Normal,
763                    where_bound_origin: None,
764                };
765                self.with(scope, |this| {
766                    // a bare fn has no bounds, so everything
767                    // contained within is scoped within its binder.
768                    intravisit::walk_ty(this, ty);
769                });
770            }
771            hir::TyKind::TraitObject(bounds, lifetime) => {
772                let lifetime = lifetime.pointer();
773
774                debug!(?bounds, ?lifetime, "TraitObject");
775                let scope = Scope::TraitRefBoundary { s: self.scope };
776                self.with(scope, |this| {
777                    for bound in bounds {
778                        this.visit_poly_trait_ref_inner(
779                            bound,
780                            NonLifetimeBinderAllowed::Deny("trait object types"),
781                        );
782                    }
783                });
784                match lifetime.res {
785                    LifetimeName::ImplicitObjectLifetimeDefault => {
786                        // If the user does not write *anything*, we
787                        // use the object lifetime defaulting
788                        // rules. So e.g., `Box<dyn Debug>` becomes
789                        // `Box<dyn Debug + 'static>`.
790                        self.resolve_object_lifetime_default(&*lifetime)
791                    }
792                    LifetimeName::Infer => {
793                        // If the user writes `'_`, we use the *ordinary* elision
794                        // rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
795                        // resolved the same as the `'_` in `&'_ Foo`.
796                        //
797                        // cc #48468
798                    }
799                    LifetimeName::Param(..) | LifetimeName::Static => {
800                        // If the user wrote an explicit name, use that.
801                        self.visit_lifetime(&*lifetime);
802                    }
803                    LifetimeName::Error => {}
804                }
805            }
806            hir::TyKind::Ref(lifetime_ref, ref mt) => {
807                self.visit_lifetime(lifetime_ref);
808                let scope = Scope::ObjectLifetimeDefault {
809                    lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
810                    s: self.scope,
811                };
812                self.with(scope, |this| this.visit_ty_unambig(mt.ty));
813            }
814            hir::TyKind::TraitAscription(bounds) => {
815                let scope = Scope::TraitRefBoundary { s: self.scope };
816                self.with(scope, |this| {
817                    let scope = Scope::LateBoundary {
818                        s: this.scope,
819                        what: "`impl Trait` in binding",
820                        deny_late_regions: true,
821                    };
822                    this.with(scope, |this| {
823                        for bound in bounds {
824                            this.visit_param_bound(bound);
825                        }
826                    })
827                });
828            }
829            _ => intravisit::walk_ty(self, ty),
830        }
831    }
832
833    #[instrument(level = "debug", skip(self))]
834    fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
835        intravisit::walk_ty_pat(self, p)
836    }
837
838    #[instrument(level = "debug", skip(self))]
839    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
840        use self::hir::TraitItemKind::*;
841        match trait_item.kind {
842            Fn(_, _) => {
843                self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
844                    intravisit::walk_trait_item(this, trait_item)
845                });
846            }
847            Type(bounds, ty) => {
848                self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
849                    this.visit_generics(trait_item.generics);
850                    for bound in bounds {
851                        this.visit_param_bound(bound);
852                    }
853                    if let Some(ty) = ty {
854                        this.visit_ty_unambig(ty);
855                    }
856                })
857            }
858            Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
859                intravisit::walk_trait_item(this, trait_item)
860            }),
861        }
862    }
863
864    #[instrument(level = "debug", skip(self))]
865    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
866        use self::hir::ImplItemKind::*;
867        match impl_item.kind {
868            Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
869                intravisit::walk_impl_item(this, impl_item)
870            }),
871            Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
872                this.visit_generics(impl_item.generics);
873                this.visit_ty_unambig(ty);
874            }),
875            Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
876                intravisit::walk_impl_item(this, impl_item)
877            }),
878        }
879    }
880
881    #[instrument(level = "debug", skip(self))]
882    fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
883        match lifetime_ref.res {
884            hir::LifetimeName::Static => {
885                self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
886            }
887            hir::LifetimeName::Param(param_def_id) => {
888                self.resolve_lifetime_ref(param_def_id, lifetime_ref)
889            }
890            // If we've already reported an error, just ignore `lifetime_ref`.
891            hir::LifetimeName::Error => {}
892            // Those will be resolved by typechecking.
893            hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
894        }
895    }
896
897    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
898        for (i, segment) in path.segments.iter().enumerate() {
899            let depth = path.segments.len() - i - 1;
900            if let Some(args) = segment.args {
901                self.visit_segment_args(path.res, depth, args);
902            }
903        }
904        if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
905            self.resolve_type_ref(param_def_id.expect_local(), hir_id);
906        }
907    }
908
909    fn visit_fn(
910        &mut self,
911        fk: intravisit::FnKind<'tcx>,
912        fd: &'tcx hir::FnDecl<'tcx>,
913        body_id: hir::BodyId,
914        _: Span,
915        def_id: LocalDefId,
916    ) {
917        let output = match fd.output {
918            hir::FnRetTy::DefaultReturn(_) => None,
919            hir::FnRetTy::Return(ty) => Some(ty),
920        };
921        if let Some(ty) = output
922            && let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
923        {
924            let bound_vars: Vec<_> =
925                self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
926            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
927            self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
928        }
929        self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
930        intravisit::walk_fn_kind(self, fk);
931        self.visit_nested_body(body_id)
932    }
933
934    fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
935        let scope = Scope::TraitRefBoundary { s: self.scope };
936        self.with(scope, |this| {
937            walk_list!(this, visit_generic_param, generics.params);
938            walk_list!(this, visit_where_predicate, generics.predicates);
939        })
940    }
941
942    fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
943        let hir_id = predicate.hir_id;
944        match predicate.kind {
945            &hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
946                bounded_ty,
947                bounds,
948                bound_generic_params,
949                origin,
950                ..
951            }) => {
952                let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
953                    bound_generic_params
954                        .iter()
955                        .enumerate()
956                        .map(|(late_bound_idx, param)| {
957                            (
958                                (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
959                                late_arg_as_bound_arg(self.tcx, param),
960                            )
961                        })
962                        .unzip();
963
964                self.record_late_bound_vars(hir_id, binders);
965
966                // If this is an RTN type in the self type, then append those to the binder.
967                self.try_append_return_type_notation_params(hir_id, bounded_ty);
968
969                // Even if there are no lifetimes defined here, we still wrap it in a binder
970                // scope. If there happens to be a nested poly trait ref (an error), that
971                // will be `Concatenating` anyways, so we don't have to worry about the depth
972                // being wrong.
973                let scope = Scope::Binder {
974                    hir_id,
975                    bound_vars,
976                    s: self.scope,
977                    scope_type: BinderScopeType::Normal,
978                    where_bound_origin: Some(origin),
979                };
980                self.with(scope, |this| {
981                    walk_list!(this, visit_generic_param, bound_generic_params);
982                    this.visit_ty_unambig(bounded_ty);
983                    walk_list!(this, visit_param_bound, bounds);
984                })
985            }
986            &hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
987                lifetime,
988                bounds,
989                ..
990            }) => {
991                self.visit_lifetime(lifetime);
992                walk_list!(self, visit_param_bound, bounds);
993            }
994            &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
995                lhs_ty, rhs_ty, ..
996            }) => {
997                self.visit_ty_unambig(lhs_ty);
998                self.visit_ty_unambig(rhs_ty);
999            }
1000        }
1001    }
1002
1003    fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
1004        self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
1005    }
1006
1007    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
1008        self.with(
1009            Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
1010            |this| {
1011                intravisit::walk_anon_const(this, c);
1012            },
1013        );
1014    }
1015
1016    fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
1017        match p.kind {
1018            GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1019                self.resolve_type_ref(p.def_id, p.hir_id);
1020            }
1021            GenericParamKind::Lifetime { .. } => {
1022                // No need to resolve lifetime params, we don't use them for things
1023                // like implicit `?Sized` or const-param-has-ty predicates.
1024            }
1025        }
1026
1027        match p.kind {
1028            GenericParamKind::Lifetime { .. } => {}
1029            GenericParamKind::Type { default, .. } => {
1030                if let Some(ty) = default {
1031                    self.visit_ty_unambig(ty);
1032                }
1033            }
1034            GenericParamKind::Const { ty, default, .. } => {
1035                self.visit_ty_unambig(ty);
1036                if let Some(default) = default {
1037                    self.visit_const_arg_unambig(default);
1038                }
1039            }
1040        }
1041    }
1042}
1043
1044fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
1045    debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
1046    let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(param_def_id) else {
1047        bug!("expected GenericParam for object_lifetime_default");
1048    };
1049    match param.source {
1050        hir::GenericParamSource::Generics => {
1051            let parent_def_id = tcx.local_parent(param_def_id);
1052            let generics = tcx.hir_get_generics(parent_def_id).unwrap();
1053            let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1054            let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1055
1056            // Scan the bounds and where-clauses on parameters to extract bounds
1057            // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
1058            // for each type parameter.
1059            match param.kind {
1060                GenericParamKind::Type { .. } => {
1061                    let mut set = Set1::Empty;
1062
1063                    // Look for `type: ...` where clauses.
1064                    for bound in generics.bounds_for_param(param_def_id) {
1065                        // Ignore `for<'a> type: ...` as they can change what
1066                        // lifetimes mean (although we could "just" handle it).
1067                        if !bound.bound_generic_params.is_empty() {
1068                            continue;
1069                        }
1070
1071                        for bound in bound.bounds {
1072                            if let hir::GenericBound::Outlives(lifetime) = bound {
1073                                set.insert(lifetime.res);
1074                            }
1075                        }
1076                    }
1077
1078                    match set {
1079                        Set1::Empty => ObjectLifetimeDefault::Empty,
1080                        Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1081                        Set1::One(hir::LifetimeName::Param(param_def_id)) => {
1082                            ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1083                        }
1084                        _ => ObjectLifetimeDefault::Ambiguous,
1085                    }
1086                }
1087                _ => {
1088                    bug!("object_lifetime_default_raw must only be called on a type parameter")
1089                }
1090            }
1091        }
1092        hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
1093    }
1094}
1095
1096impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1097    fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1098    where
1099        F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
1100    {
1101        let BoundVarContext { tcx, rbv, .. } = self;
1102        let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
1103        let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
1104        {
1105            let _enter = span.enter();
1106            f(&mut this);
1107        }
1108    }
1109
1110    fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
1111        if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
1112            bug!(
1113                "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1114                self.rbv.late_bound_vars[&hir_id.local_id]
1115            )
1116        }
1117    }
1118
1119    /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
1120    ///
1121    /// Handles visiting fns and methods. These are a bit complicated because we must distinguish
1122    /// early- vs late-bound lifetime parameters. We do this by checking which lifetimes appear
1123    /// within type bounds; those are early bound lifetimes, and the rest are late bound.
1124    ///
1125    /// For example:
1126    ///
1127    ///    fn foo<'a,'b,'c,T:Trait<'b>>(...)
1128    ///
1129    /// Here `'a` and `'c` are late bound but `'b` is early bound. Note that early- and late-bound
1130    /// lifetimes may be interspersed together.
1131    ///
1132    /// If early bound lifetimes are present, we separate them into their own list (and likewise
1133    /// for late bound). They will be numbered sequentially, starting from the lowest index that is
1134    /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
1135    /// bound lifetimes are resolved by name and associated with a binder ID (`binder_id`), so the
1136    /// ordering is not important there.
1137    fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1138    where
1139        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1140    {
1141        let mut named_late_bound_vars = 0;
1142        let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
1143            .params
1144            .iter()
1145            .map(|param| {
1146                (
1147                    param.def_id,
1148                    match param.kind {
1149                        GenericParamKind::Lifetime { .. } => {
1150                            if self.tcx.is_late_bound(param.hir_id) {
1151                                let late_bound_idx = named_late_bound_vars;
1152                                named_late_bound_vars += 1;
1153                                ResolvedArg::late(late_bound_idx, param)
1154                            } else {
1155                                ResolvedArg::early(param)
1156                            }
1157                        }
1158                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1159                            ResolvedArg::early(param)
1160                        }
1161                    },
1162                )
1163            })
1164            .collect();
1165
1166        let binders: Vec<_> = generics
1167            .params
1168            .iter()
1169            .filter(|param| {
1170                matches!(param.kind, GenericParamKind::Lifetime { .. })
1171                    && self.tcx.is_late_bound(param.hir_id)
1172            })
1173            .map(|param| late_arg_as_bound_arg(self.tcx, param))
1174            .collect();
1175        self.record_late_bound_vars(hir_id, binders);
1176        let scope = Scope::Binder {
1177            hir_id,
1178            bound_vars,
1179            s: self.scope,
1180            scope_type: BinderScopeType::Normal,
1181            where_bound_origin: None,
1182        };
1183        self.with(scope, walk);
1184    }
1185
1186    fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1187    where
1188        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1189    {
1190        let bound_vars =
1191            generics.params.iter().map(|param| (param.def_id, ResolvedArg::early(param))).collect();
1192        self.record_late_bound_vars(hir_id, vec![]);
1193        let scope = Scope::Binder {
1194            hir_id,
1195            bound_vars,
1196            s: self.scope,
1197            scope_type: BinderScopeType::Normal,
1198            where_bound_origin: None,
1199        };
1200        self.with(scope, |this| {
1201            let scope = Scope::TraitRefBoundary { s: this.scope };
1202            this.with(scope, walk)
1203        });
1204    }
1205
1206    #[instrument(level = "debug", skip(self))]
1207    fn resolve_lifetime_ref(
1208        &mut self,
1209        region_def_id: LocalDefId,
1210        lifetime_ref: &'tcx hir::Lifetime,
1211    ) {
1212        // Walk up the scope chain, tracking the number of fn scopes
1213        // that we pass through, until we find a lifetime with the
1214        // given name or we run out of scopes.
1215        // search.
1216        let mut late_depth = 0;
1217        let mut scope = self.scope;
1218        let mut outermost_body = None;
1219        let mut crossed_late_boundary = None;
1220        let mut opaque_capture_scopes = vec![];
1221        let result = loop {
1222            match *scope {
1223                Scope::Body { id, s } => {
1224                    outermost_body = Some(id);
1225                    scope = s;
1226                }
1227
1228                Scope::Root { opt_parent_item } => {
1229                    if let Some(parent_item) = opt_parent_item
1230                        && let parent_generics = self.tcx.generics_of(parent_item)
1231                        && parent_generics
1232                            .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
1233                            .is_some()
1234                    {
1235                        break Some(ResolvedArg::EarlyBound(region_def_id));
1236                    }
1237                    break None;
1238                }
1239
1240                Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1241                    if let Some(&def) = bound_vars.get(&region_def_id) {
1242                        break Some(def.shifted(late_depth));
1243                    }
1244                    match scope_type {
1245                        BinderScopeType::Normal => late_depth += 1,
1246                        BinderScopeType::Concatenating => {}
1247                    }
1248                    // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
1249                    // regular fns.
1250                    if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1251                        && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
1252                        && let Some(generics) =
1253                            self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
1254                        && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1255                        && param.is_elided_lifetime()
1256                        && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
1257                        && !self.tcx.features().anonymous_lifetime_in_impl_trait()
1258                    {
1259                        let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
1260                            &self.tcx.sess,
1261                            sym::anonymous_lifetime_in_impl_trait,
1262                            lifetime_ref.ident.span,
1263                            "anonymous lifetimes in `impl Trait` are unstable",
1264                        );
1265
1266                        if let Some(generics) =
1267                            self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
1268                        {
1269                            let new_param_sugg =
1270                                if let Some(span) = generics.span_for_lifetime_suggestion() {
1271                                    (span, "'a, ".to_owned())
1272                                } else {
1273                                    (generics.span, "<'a>".to_owned())
1274                                };
1275
1276                            let lifetime_sugg = lifetime_ref.suggestion("'a");
1277                            let suggestions = vec![lifetime_sugg, new_param_sugg];
1278
1279                            diag.span_label(
1280                                lifetime_ref.ident.span,
1281                                "expected named lifetime parameter",
1282                            );
1283                            diag.multipart_suggestion(
1284                                "consider introducing a named lifetime parameter",
1285                                suggestions,
1286                                rustc_errors::Applicability::MaybeIncorrect,
1287                            );
1288                        }
1289
1290                        diag.emit();
1291                        return;
1292                    }
1293                    scope = s;
1294                }
1295
1296                Scope::Opaque { captures, def_id, s } => {
1297                    opaque_capture_scopes.push((def_id, captures));
1298                    late_depth = 0;
1299                    scope = s;
1300                }
1301
1302                Scope::ObjectLifetimeDefault { s, .. }
1303                | Scope::Supertrait { s, .. }
1304                | Scope::TraitRefBoundary { s, .. } => {
1305                    scope = s;
1306                }
1307
1308                Scope::LateBoundary { s, what, deny_late_regions } => {
1309                    if deny_late_regions {
1310                        crossed_late_boundary = Some(what);
1311                    }
1312                    scope = s;
1313                }
1314            }
1315        };
1316
1317        if let Some(mut def) = result {
1318            def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
1319
1320            if let ResolvedArg::EarlyBound(..) = def {
1321                // Do not free early-bound regions, only late-bound ones.
1322            } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
1323                && let Some(what) = crossed_late_boundary
1324            {
1325                let use_span = lifetime_ref.ident.span;
1326                let def_span = self.tcx.def_span(param_def_id);
1327                let guar = match self.tcx.def_kind(param_def_id) {
1328                    DefKind::LifetimeParam => {
1329                        self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Lifetime {
1330                            use_span,
1331                            def_span,
1332                            what,
1333                        })
1334                    }
1335                    kind => span_bug!(
1336                        use_span,
1337                        "did not expect to resolve lifetime to {}",
1338                        kind.descr(param_def_id.to_def_id())
1339                    ),
1340                };
1341                def = ResolvedArg::Error(guar);
1342            } else if let Some(body_id) = outermost_body {
1343                let fn_id = self.tcx.hir().body_owner(body_id);
1344                match self.tcx.hir_node(fn_id) {
1345                    Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
1346                    | Node::TraitItem(hir::TraitItem {
1347                        owner_id,
1348                        kind: hir::TraitItemKind::Fn(..),
1349                        ..
1350                    })
1351                    | Node::ImplItem(hir::ImplItem {
1352                        owner_id,
1353                        kind: hir::ImplItemKind::Fn(..),
1354                        ..
1355                    }) => {
1356                        def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
1357                    }
1358                    Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1359                        def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
1360                    }
1361                    _ => {}
1362                }
1363            }
1364
1365            self.insert_lifetime(lifetime_ref, def);
1366            return;
1367        }
1368
1369        // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
1370        // AST-based resolution does not care for impl-trait desugaring, which are the
1371        // responsibility of lowering. This may create a mismatch between the resolution
1372        // AST found (`region_def_id`) which points to HRTB, and what HIR allows.
1373        // ```
1374        // fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
1375        // ```
1376        //
1377        // In such case, walk back the binders to diagnose it properly.
1378        let mut scope = self.scope;
1379        loop {
1380            match *scope {
1381                Scope::Binder {
1382                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1383                } => {
1384                    self.tcx.dcx().emit_err(errors::LateBoundInApit::Lifetime {
1385                        span: lifetime_ref.ident.span,
1386                        param_span: self.tcx.def_span(region_def_id),
1387                    });
1388                    return;
1389                }
1390                Scope::Root { .. } => break,
1391                Scope::Binder { s, .. }
1392                | Scope::Body { s, .. }
1393                | Scope::Opaque { s, .. }
1394                | Scope::ObjectLifetimeDefault { s, .. }
1395                | Scope::Supertrait { s, .. }
1396                | Scope::TraitRefBoundary { s, .. }
1397                | Scope::LateBoundary { s, .. } => {
1398                    scope = s;
1399                }
1400            }
1401        }
1402
1403        self.tcx.dcx().span_delayed_bug(
1404            lifetime_ref.ident.span,
1405            format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1406        );
1407    }
1408
1409    /// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
1410    /// and ban them. Type variables instantiated inside binders aren't
1411    /// well-supported at the moment, so this doesn't work.
1412    /// In the future, this should be fixed and this error should be removed.
1413    fn check_lifetime_is_capturable(
1414        &self,
1415        opaque_def_id: LocalDefId,
1416        lifetime: ResolvedArg,
1417        capture_span: Span,
1418    ) -> Result<(), ErrorGuaranteed> {
1419        let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
1420        let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
1421        let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
1422            // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
1423            // it must be a reified late-bound lifetime from a trait goal.
1424            hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
1425            // Other items are fine.
1426            hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
1427            hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
1428                "higher-ranked lifetime from function pointer"
1429            }
1430            hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
1431                "higher-ranked lifetime from `dyn` type"
1432            }
1433            _ => "higher-ranked lifetime",
1434        };
1435
1436        let decl_span = self.tcx.def_span(lifetime_def_id);
1437        let (span, label) = if capture_span != decl_span {
1438            (capture_span, None)
1439        } else {
1440            let opaque_span = self.tcx.def_span(opaque_def_id);
1441            (opaque_span, Some(opaque_span))
1442        };
1443
1444        // Ensure that the parent of the def is an item, not HRTB
1445        let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
1446            span,
1447            label,
1448            decl_span,
1449            bad_place,
1450        });
1451        Err(guar)
1452    }
1453
1454    #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
1455    fn remap_opaque_captures(
1456        &self,
1457        opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
1458        mut lifetime: ResolvedArg,
1459        ident: Ident,
1460    ) -> ResolvedArg {
1461        if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
1462            if let Err(guar) =
1463                self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
1464            {
1465                lifetime = ResolvedArg::Error(guar);
1466            }
1467        }
1468
1469        for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
1470            let mut captures = captures.borrow_mut();
1471            let remapped = *captures.entry(lifetime).or_insert_with(|| {
1472                let feed = self.tcx.create_def(opaque_def_id, ident.name, DefKind::LifetimeParam);
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::AssocKind::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::AssocKind::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_name: Ident,
1884        assoc_kind: ty::AssocKind,
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_name_and_kind(
1888                tcx,
1889                assoc_name,
1890                assoc_kind,
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 as
1904            // 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_name));
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::AssocKind::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(trait_ref), .. }) = 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) = 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::AssocKind::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(
2170        &self,
2171        expected_res: Res,
2172    ) -> impl Iterator<Item = DefId> + use<'tcx, '_> {
2173        std::iter::from_coroutine(
2174            #[coroutine]
2175            move || {
2176                let mut scope = self.scope;
2177                loop {
2178                    let hir_id = match *scope {
2179                        Scope::Binder { hir_id, .. } => Some(hir_id),
2180                        Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2181                            Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2182                        }
2183                        Scope::Body { .. }
2184                        | Scope::ObjectLifetimeDefault { .. }
2185                        | Scope::Supertrait { .. }
2186                        | Scope::TraitRefBoundary { .. }
2187                        | Scope::LateBoundary { .. }
2188                        | Scope::Opaque { .. }
2189                        | Scope::Root { opt_parent_item: None } => None,
2190                    };
2191
2192                    if let Some(hir_id) = hir_id {
2193                        let node = self.tcx.hir_node(hir_id);
2194                        // If this is a `Self` bound in a trait, yield the trait itself.
2195                        // Specifically, we don't need to look at any supertraits since
2196                        // we already do that in `BoundVarContext::supertrait_hrtb_vars`.
2197                        if let Res::SelfTyParam { trait_: _ } = expected_res
2198                            && let hir::Node::Item(item) = node
2199                            && let hir::ItemKind::Trait(..) = item.kind
2200                        {
2201                            // Yield the trait's def id. Supertraits will be
2202                            // elaborated from that.
2203                            yield item.owner_id.def_id.to_def_id();
2204                        } else if let Some(generics) = node.generics() {
2205                            for pred in generics.predicates {
2206                                let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
2207                                else {
2208                                    continue;
2209                                };
2210                                let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2211                                    pred.bounded_ty.kind
2212                                else {
2213                                    continue;
2214                                };
2215                                // Match the expected res.
2216                                if bounded_path.res != expected_res {
2217                                    continue;
2218                                }
2219                                for pred in pred.bounds {
2220                                    match pred {
2221                                        hir::GenericBound::Trait(poly_trait_ref) => {
2222                                            if let Some(def_id) =
2223                                                poly_trait_ref.trait_ref.trait_def_id()
2224                                            {
2225                                                yield def_id;
2226                                            }
2227                                        }
2228                                        hir::GenericBound::Outlives(_)
2229                                        | hir::GenericBound::Use(_, _) => {}
2230                                    }
2231                                }
2232                            }
2233                        }
2234                    }
2235
2236                    match *scope {
2237                        Scope::Binder { s, .. }
2238                        | Scope::Body { s, .. }
2239                        | Scope::ObjectLifetimeDefault { s, .. }
2240                        | Scope::Supertrait { s, .. }
2241                        | Scope::TraitRefBoundary { s }
2242                        | Scope::LateBoundary { s, .. }
2243                        | Scope::Opaque { s, .. } => {
2244                            scope = s;
2245                        }
2246                        Scope::Root { .. } => break,
2247                    }
2248                }
2249            },
2250        )
2251    }
2252}
2253
2254/// Detects late-bound lifetimes and inserts them into
2255/// `late_bound`.
2256///
2257/// A region declared on a fn is **late-bound** if:
2258/// - it is constrained by an argument type;
2259/// - it does not appear in a where-clause.
2260///
2261/// "Constrained" basically means that it appears in any type but
2262/// not amongst the inputs to a projection. In other words, `<&'a
2263/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
2264fn is_late_bound_map(
2265    tcx: TyCtxt<'_>,
2266    owner_id: hir::OwnerId,
2267) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2268    let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
2269    let generics = tcx.hir_get_generics(owner_id.def_id)?;
2270
2271    let mut late_bound = FxIndexSet::default();
2272
2273    let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2274    for arg_ty in sig.decl.inputs {
2275        constrained_by_input.visit_ty_unambig(arg_ty);
2276    }
2277
2278    let mut appears_in_output =
2279        AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
2280    intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2281    if appears_in_output.has_fully_capturing_opaque {
2282        appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2283    }
2284
2285    debug!(?constrained_by_input.regions);
2286
2287    // Walk the lifetimes that appear in where clauses.
2288    //
2289    // Subtle point: because we disallow nested bindings, we can just
2290    // ignore binders here and scrape up all names we see.
2291    let mut appears_in_where_clause =
2292        AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
2293    appears_in_where_clause.visit_generics(generics);
2294    debug!(?appears_in_where_clause.regions);
2295
2296    // Late bound regions are those that:
2297    // - appear in the inputs
2298    // - do not appear in the where-clauses
2299    // - are not implicitly captured by `impl Trait`
2300    for param in generics.params {
2301        match param.kind {
2302            hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
2303
2304            // Neither types nor consts are late-bound.
2305            hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2306        }
2307
2308        // appears in the where clauses? early-bound.
2309        if appears_in_where_clause.regions.contains(&param.def_id) {
2310            continue;
2311        }
2312
2313        // does not appear in the inputs, but appears in the return type? early-bound.
2314        if !constrained_by_input.regions.contains(&param.def_id)
2315            && appears_in_output.regions.contains(&param.def_id)
2316        {
2317            continue;
2318        }
2319
2320        debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2321
2322        let inserted = late_bound.insert(param.hir_id.local_id);
2323        assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2324    }
2325
2326    debug!(?late_bound);
2327    return Some(tcx.arena.alloc(late_bound));
2328
2329    /// Visits a `ty::Ty` collecting information about what generic parameters are constrained.
2330    ///
2331    /// The visitor does not operate on `hir::Ty` so that it can be called on the rhs of a `type Alias<...> = ...;`
2332    /// which may live in a separate crate so there would not be any hir available. Instead we use the `type_of`
2333    /// query to obtain a `ty::Ty` which will be present even in cross crate scenarios. It also naturally
2334    /// handles cycle detection as we go through the query system.
2335    ///
2336    /// This is necessary in the first place for the following case:
2337    /// ```rust,ignore (pseudo-Rust)
2338    /// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
2339    /// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
2340    /// ```
2341    ///
2342    /// If we conservatively considered `'a` unconstrained then we could break users who had written code before
2343    /// we started correctly handling aliases. If we considered `'a` constrained then it would become late bound
2344    /// causing an error during HIR ty lowering as the `'a` is not constrained by the input type `<() as Trait<'a>>::Assoc`
2345    /// but appears in the output type `<() as Trait<'a>>::Assoc`.
2346    ///
2347    /// We must therefore "look into" the `Alias` to see whether we should consider `'a` constrained or not.
2348    ///
2349    /// See #100508 #85533 #47511 for additional context
2350    struct ConstrainedCollectorPostHirTyLowering {
2351        arg_is_constrained: Box<[bool]>,
2352    }
2353
2354    use ty::Ty;
2355    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2356        fn visit_ty(&mut self, t: Ty<'tcx>) {
2357            match t.kind() {
2358                ty::Param(param_ty) => {
2359                    self.arg_is_constrained[param_ty.index as usize] = true;
2360                }
2361                ty::Alias(ty::Projection | ty::Inherent, _) => return,
2362                _ => (),
2363            }
2364            t.super_visit_with(self)
2365        }
2366
2367        fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2368
2369        fn visit_region(&mut self, r: ty::Region<'tcx>) {
2370            debug!("r={:?}", r.kind());
2371            if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2372                self.arg_is_constrained[region.index as usize] = true;
2373            }
2374        }
2375    }
2376
2377    struct ConstrainedCollector<'tcx> {
2378        tcx: TyCtxt<'tcx>,
2379        regions: FxHashSet<LocalDefId>,
2380    }
2381
2382    impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2383        fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2384            match ty.kind {
2385                hir::TyKind::Path(
2386                    hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2387                ) => {
2388                    // ignore lifetimes appearing in associated type
2389                    // projections, as they are not *constrained*
2390                    // (defined above)
2391                }
2392
2393                hir::TyKind::Path(hir::QPath::Resolved(
2394                    None,
2395                    hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2396                )) => {
2397                    // See comments on `ConstrainedCollectorPostHirTyLowering` for why this arm does not
2398                    // just consider args to be unconstrained.
2399                    let generics = self.tcx.generics_of(alias_def);
2400                    let mut walker = ConstrainedCollectorPostHirTyLowering {
2401                        arg_is_constrained: vec![false; generics.own_params.len()]
2402                            .into_boxed_slice(),
2403                    };
2404                    walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2405
2406                    match segments.last() {
2407                        Some(hir::PathSegment { args: Some(args), .. }) => {
2408                            let tcx = self.tcx;
2409                            for constrained_arg in
2410                                args.args.iter().enumerate().flat_map(|(n, arg)| {
2411                                    match walker.arg_is_constrained.get(n) {
2412                                        Some(true) => Some(arg),
2413                                        Some(false) => None,
2414                                        None => {
2415                                            tcx.dcx().span_delayed_bug(
2416                                                *span,
2417                                                format!(
2418                                                    "Incorrect generic arg count for alias {alias_def:?}"
2419                                                ),
2420                                            );
2421                                            None
2422                                        }
2423                                    }
2424                                })
2425                            {
2426                                self.visit_generic_arg(constrained_arg);
2427                            }
2428                        }
2429                        Some(_) => (),
2430                        None => bug!("Path with no segments or self type"),
2431                    }
2432                }
2433
2434                hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2435                    // consider only the lifetimes on the final
2436                    // segment; I am not sure it's even currently
2437                    // valid to have them elsewhere, but even if it
2438                    // is, those would be potentially inputs to
2439                    // projections
2440                    if let Some(last_segment) = path.segments.last() {
2441                        self.visit_path_segment(last_segment);
2442                    }
2443                }
2444
2445                _ => {
2446                    intravisit::walk_ty(self, ty);
2447                }
2448            }
2449        }
2450
2451        fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2452            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2453                self.regions.insert(def_id);
2454            }
2455        }
2456    }
2457
2458    struct AllCollector<'tcx> {
2459        tcx: TyCtxt<'tcx>,
2460        has_fully_capturing_opaque: bool,
2461        regions: FxHashSet<LocalDefId>,
2462    }
2463
2464    impl<'v> Visitor<'v> for AllCollector<'v> {
2465        fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2466            if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2467                self.regions.insert(def_id);
2468            }
2469        }
2470
2471        fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
2472            if !self.has_fully_capturing_opaque {
2473                self.has_fully_capturing_opaque =
2474                    opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
2475            }
2476            intravisit::walk_opaque_ty(self, opaque);
2477        }
2478    }
2479}
2480
2481fn deny_non_region_late_bound(
2482    tcx: TyCtxt<'_>,
2483    bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2484    where_: &str,
2485) {
2486    let mut first = true;
2487
2488    for (var, arg) in bound_vars {
2489        let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2490            span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2491        };
2492
2493        let what = match param.kind {
2494            hir::GenericParamKind::Type { .. } => "type",
2495            hir::GenericParamKind::Const { .. } => "const",
2496            hir::GenericParamKind::Lifetime { .. } => continue,
2497        };
2498
2499        let diag = tcx.dcx().struct_span_err(
2500            param.span,
2501            format!("late-bound {what} parameter not allowed on {where_}"),
2502        );
2503
2504        let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
2505
2506        first = false;
2507        *arg = ResolvedArg::Error(guar);
2508    }
2509}