rustc_hir_analysis/collect/
resolve_bound_vars.rs

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