rustc_hir_analysis/collect/
resolve_bound_vars.rs

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