1use 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 Binder {
78 bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
81
82 scope_type: BinderScopeType,
83
84 hir_id: HirId,
89
90 s: ScopeRef<'a>,
91
92 where_bound_origin: Option<hir::PredicateOrigin>,
98 },
99
100 Body {
105 id: hir::BodyId,
106 s: ScopeRef<'a>,
107 },
108
109 ObjectLifetimeDefault {
113 lifetime: Option<ResolvedArg>,
114 s: ScopeRef<'a>,
115 },
116
117 Supertrait {
122 bound_vars: Vec<ty::BoundVariableKind>,
123 s: ScopeRef<'a>,
124 },
125
126 TraitRefBoundary {
127 s: ScopeRef<'a>,
128 },
129
130 Opaque {
139 def_id: LocalDefId,
141 captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
143
144 s: ScopeRef<'a>,
145 },
146
147 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 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 Normal,
211 Concatenating,
221}
222
223type ScopeRef<'a> = &'a Scope<'a>;
224
225pub(crate) fn provide(providers: &mut Providers) {
227 *providers = Providers {
228 resolve_bound_vars,
229
230 named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
231 is_late_bound_map,
232 object_lifetime_default,
233 late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
234 opaque_captured_lifetimes: |tcx, id| {
235 &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
236 .opaque_captured_lifetimes
237 .get(&id)
238 .map_or(&[][..], |x| &x[..])
239 },
240
241 ..*providers
242 };
243}
244
245#[instrument(level = "debug", skip(tcx))]
249fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
250 let mut rbv = ResolveBoundVars::default();
251 let mut visitor = BoundVarContext {
252 tcx,
253 rbv: &mut rbv,
254 scope: &Scope::Root { opt_parent_item: None },
255 disambiguator: &mut DisambiguatorState::new(),
256 };
257 match tcx.hir_owner_node(local_def_id) {
258 hir::OwnerNode::Item(item) => visitor.visit_item(item),
259 hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
260 hir::OwnerNode::TraitItem(item) => {
261 let scope =
262 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
263 visitor.scope = &scope;
264 visitor.visit_trait_item(item)
265 }
266 hir::OwnerNode::ImplItem(item) => {
267 let scope =
268 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
269 visitor.scope = &scope;
270 visitor.visit_impl_item(item)
271 }
272 hir::OwnerNode::Crate(_) => {}
273 hir::OwnerNode::Synthetic => unreachable!(),
274 }
275
276 debug!(?rbv.defs);
277 debug!(?rbv.late_bound_vars);
278 debug!(?rbv.opaque_captured_lifetimes);
279 rbv
280}
281
282fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind {
283 let def_id = param.def_id.to_def_id();
284 match param.kind {
285 GenericParamKind::Lifetime { .. } => {
286 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id))
287 }
288 GenericParamKind::Type { .. } => ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)),
289 GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
290 }
291}
292
293fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
297 match param.kind {
298 ty::GenericParamDefKind::Lifetime => {
299 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id))
300 }
301 ty::GenericParamDefKind::Type { .. } => {
302 ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id))
303 }
304 ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
305 }
306}
307
308fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
312 match opaque.origin {
313 _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
316 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
317 _ if opaque.span.at_least_rust_2024() => true,
318 hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
319 }
320}
321
322impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
323 fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
325 let mut scope = self.scope;
326 let mut supertrait_bound_vars = vec![];
327 loop {
328 match scope {
329 Scope::Body { .. } | Scope::Root { .. } => {
330 break (vec![], BinderScopeType::Normal);
331 }
332
333 Scope::Opaque { s, .. }
334 | Scope::ObjectLifetimeDefault { s, .. }
335 | Scope::LateBoundary { s, .. } => {
336 scope = s;
337 }
338
339 Scope::Supertrait { s, bound_vars } => {
340 supertrait_bound_vars = bound_vars.clone();
341 scope = s;
342 }
343
344 Scope::TraitRefBoundary { .. } => {
345 if !supertrait_bound_vars.is_empty() {
349 self.tcx.dcx().delayed_bug(format!(
350 "found supertrait lifetimes without a binder to append \
351 them to: {supertrait_bound_vars:?}"
352 ));
353 }
354 break (vec![], BinderScopeType::Normal);
355 }
356
357 Scope::Binder { hir_id, .. } => {
358 let mut full_binders =
360 self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
361 full_binders.extend(supertrait_bound_vars);
362 break (full_binders, BinderScopeType::Concatenating);
363 }
364 }
365 }
366 }
367
368 fn visit_poly_trait_ref_inner(
369 &mut self,
370 trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
371 non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
372 ) {
373 debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
374
375 let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
376
377 let initial_bound_vars = binders.len() as u32;
378 let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
379 let binders_iter =
380 trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
381 let arg = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
382 bound_vars.insert(param.def_id, arg);
383 late_arg_as_bound_arg(param)
384 });
385 binders.extend(binders_iter);
386
387 if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
388 deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
389 }
390
391 debug!(?binders);
392 self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
393
394 let scope = Scope::Binder {
399 hir_id: trait_ref.trait_ref.hir_ref_id,
400 bound_vars,
401 s: self.scope,
402 scope_type,
403 where_bound_origin: None,
404 };
405 self.with(scope, |this| {
406 walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
407 this.visit_trait_ref(&trait_ref.trait_ref);
408 });
409 }
410}
411
412enum NonLifetimeBinderAllowed {
413 Deny(&'static str),
414 Allow,
415}
416
417impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
418 type NestedFilter = nested_filter::OnlyBodies;
419
420 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
421 self.tcx
422 }
423
424 fn visit_nested_body(&mut self, body: hir::BodyId) {
425 let body = self.tcx.hir_body(body);
426 self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
427 this.visit_body(body);
428 });
429 }
430
431 fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
432 if let hir::ExprKind::Closure(hir::Closure {
433 binder, bound_generic_params, fn_decl, ..
434 }) = e.kind
435 {
436 if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
437 fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
438 struct FindInferInClosureWithBinder;
441 impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
442 type Result = ControlFlow<Span>;
443
444 fn visit_infer(
445 &mut self,
446 _inf_id: HirId,
447 inf_span: Span,
448 _kind: InferKind<'v>,
449 ) -> Self::Result {
450 ControlFlow::Break(inf_span)
451 }
452 }
453 FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value()
454 }
455
456 let infer_in_rt_sp = match fn_decl.output {
457 hir::FnRetTy::DefaultReturn(sp) => Some(sp),
458 hir::FnRetTy::Return(ty) => span_of_infer(ty),
459 };
460
461 let infer_spans = fn_decl
462 .inputs
463 .into_iter()
464 .filter_map(span_of_infer)
465 .chain(infer_in_rt_sp)
466 .collect::<Vec<_>>();
467
468 if !infer_spans.is_empty() {
469 self.tcx
470 .dcx()
471 .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
472 }
473 }
474
475 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
476 bound_generic_params
477 .iter()
478 .enumerate()
479 .map(|(late_bound_idx, param)| {
480 (
481 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
482 late_arg_as_bound_arg(param),
483 )
484 })
485 .unzip();
486
487 deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
488
489 self.record_late_bound_vars(e.hir_id, binders);
490 let scope = Scope::Binder {
491 hir_id: e.hir_id,
492 bound_vars,
493 s: self.scope,
494 scope_type: BinderScopeType::Normal,
495 where_bound_origin: None,
496 };
497
498 self.with(scope, |this| {
499 intravisit::walk_expr(this, e)
502 });
503 } else {
504 intravisit::walk_expr(self, e)
505 }
506 }
507
508 #[instrument(level = "debug", skip(self))]
514 fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
515 let captures = RefCell::new(FxIndexMap::default());
516
517 let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
518 if capture_all_in_scope_lifetimes {
519 let tcx = self.tcx;
520 let lifetime_ident = |def_id: LocalDefId| {
521 let name = tcx.item_name(def_id.to_def_id());
522 let span = tcx.def_span(def_id);
523 Ident::new(name, span)
524 };
525
526 let mut late_depth = 0;
530 let mut scope = self.scope;
531 let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
532 loop {
533 match *scope {
534 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
535 for (&original_lifetime, &def) in bound_vars.iter().rev() {
536 if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
537 let def = def.shifted(late_depth);
538 let ident = lifetime_ident(original_lifetime);
539 self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
540 }
541 }
542 match scope_type {
543 BinderScopeType::Normal => late_depth += 1,
544 BinderScopeType::Concatenating => {}
545 }
546 scope = s;
547 }
548
549 Scope::Root { mut opt_parent_item } => {
550 while let Some(parent_item) = opt_parent_item {
551 let parent_generics = self.tcx.generics_of(parent_item);
552 for param in parent_generics.own_params.iter().rev() {
553 if let ty::GenericParamDefKind::Lifetime = param.kind {
554 let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
555 let ident = lifetime_ident(param.def_id.expect_local());
556 self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
557 }
558 }
559 opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
560 }
561 break;
562 }
563
564 Scope::Opaque { captures, def_id, s } => {
565 opaque_capture_scopes.push((def_id, captures));
566 late_depth = 0;
567 scope = s;
568 }
569
570 Scope::Body { .. } => {
571 bug!("{:?}", scope)
572 }
573
574 Scope::ObjectLifetimeDefault { s, .. }
575 | Scope::Supertrait { s, .. }
576 | Scope::TraitRefBoundary { s, .. }
577 | Scope::LateBoundary { s, .. } => {
578 scope = s;
579 }
580 }
581 }
582 captures.borrow_mut().reverse();
583 }
584
585 let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
586 self.with(scope, |this| {
587 let scope = Scope::TraitRefBoundary { s: this.scope };
588 this.with(scope, |this| {
589 let scope = Scope::LateBoundary {
590 s: this.scope,
591 what: "nested `impl Trait`",
592 deny_late_regions: false,
595 };
596 this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
597 })
598 });
599
600 let captures = captures.into_inner().into_iter().collect();
601 debug!(?captures);
602 self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
603 }
604
605 #[instrument(level = "debug", skip(self))]
606 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
607 match &item.kind {
608 hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
609 if let Some(of_trait) = of_trait {
610 self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
611 }
612 }
613 _ => {}
614 }
615 match item.kind {
616 hir::ItemKind::Fn { generics, .. } => {
617 self.visit_early_late(item.hir_id(), generics, |this| {
618 intravisit::walk_item(this, item);
619 });
620 }
621
622 hir::ItemKind::ExternCrate(..)
623 | hir::ItemKind::Use(..)
624 | hir::ItemKind::Macro(..)
625 | hir::ItemKind::Mod(..)
626 | hir::ItemKind::ForeignMod { .. }
627 | hir::ItemKind::Static(..)
628 | hir::ItemKind::GlobalAsm { .. } => {
629 intravisit::walk_item(self, item);
631 }
632 hir::ItemKind::TyAlias(_, generics, _)
633 | hir::ItemKind::Const(_, generics, _, _)
634 | hir::ItemKind::Enum(_, generics, _)
635 | hir::ItemKind::Struct(_, generics, _)
636 | hir::ItemKind::Union(_, generics, _)
637 | hir::ItemKind::Trait(_, _, _, generics, ..)
638 | hir::ItemKind::TraitAlias(_, generics, ..)
639 | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
640 self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
642 }
643 }
644 }
645
646 fn visit_precise_capturing_arg(
647 &mut self,
648 arg: &'tcx hir::PreciseCapturingArg<'tcx>,
649 ) -> Self::Result {
650 match *arg {
651 hir::PreciseCapturingArg::Lifetime(lt) => match lt.kind {
652 LifetimeKind::Param(def_id) => {
653 self.resolve_lifetime_ref(def_id, lt);
654 }
655 LifetimeKind::Error => {}
656 LifetimeKind::ImplicitObjectLifetimeDefault
657 | LifetimeKind::Infer
658 | LifetimeKind::Static => {
659 self.tcx.dcx().emit_err(errors::BadPreciseCapture {
660 span: lt.ident.span,
661 kind: "lifetime",
662 found: format!("`{}`", lt.ident.name),
663 });
664 }
665 },
666 hir::PreciseCapturingArg::Param(param) => match param.res {
667 Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
668 | Res::SelfTyParam { trait_: def_id } => {
669 self.resolve_type_ref(def_id.expect_local(), param.hir_id);
670 }
671 Res::SelfTyAlias { alias_to, .. } => {
672 self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
673 span: param.ident.span,
674 self_span: self.tcx.def_span(alias_to),
675 what: self.tcx.def_descr(alias_to),
676 });
677 }
678 res => {
679 self.tcx.dcx().span_delayed_bug(
680 param.ident.span,
681 format!("expected type or const param, found {res:?}"),
682 );
683 }
684 },
685 }
686 }
687
688 fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
689 match item.kind {
690 hir::ForeignItemKind::Fn(_, _, generics) => {
691 self.visit_early_late(item.hir_id(), generics, |this| {
692 intravisit::walk_foreign_item(this, item);
693 })
694 }
695 hir::ForeignItemKind::Static(..) => {
696 intravisit::walk_foreign_item(self, item);
697 }
698 hir::ForeignItemKind::Type => {
699 intravisit::walk_foreign_item(self, item);
700 }
701 }
702 }
703
704 #[instrument(level = "debug", skip(self))]
705 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
706 match ty.kind {
707 hir::TyKind::FnPtr(c) => {
708 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
709 .generic_params
710 .iter()
711 .enumerate()
712 .map(|(late_bound_idx, param)| {
713 (
714 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
715 late_arg_as_bound_arg(param),
716 )
717 })
718 .unzip();
719
720 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
721
722 self.record_late_bound_vars(ty.hir_id, binders);
723 let scope = Scope::Binder {
724 hir_id: ty.hir_id,
725 bound_vars,
726 s: self.scope,
727 scope_type: BinderScopeType::Normal,
728 where_bound_origin: None,
729 };
730 self.with(scope, |this| {
731 intravisit::walk_ty(this, ty);
733 });
734 }
735 hir::TyKind::UnsafeBinder(binder) => {
736 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
737 binder
738 .generic_params
739 .iter()
740 .enumerate()
741 .map(|(late_bound_idx, param)| {
742 (
743 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
744 late_arg_as_bound_arg(param),
745 )
746 })
747 .unzip();
748
749 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
750
751 self.record_late_bound_vars(ty.hir_id, binders);
752 let scope = Scope::Binder {
753 hir_id: ty.hir_id,
754 bound_vars,
755 s: self.scope,
756 scope_type: BinderScopeType::Normal,
757 where_bound_origin: None,
758 };
759 self.with(scope, |this| {
760 intravisit::walk_ty(this, ty);
762 });
763 }
764 hir::TyKind::TraitObject(bounds, lifetime) => {
765 let lifetime = lifetime.pointer();
766
767 debug!(?bounds, ?lifetime, "TraitObject");
768 let scope = Scope::TraitRefBoundary { s: self.scope };
769 self.with(scope, |this| {
770 for bound in bounds {
771 this.visit_poly_trait_ref_inner(
772 bound,
773 NonLifetimeBinderAllowed::Deny("trait object types"),
774 );
775 }
776 });
777 match lifetime.kind {
778 LifetimeKind::ImplicitObjectLifetimeDefault => {
779 self.resolve_object_lifetime_default(&*lifetime)
784 }
785 LifetimeKind::Infer => {
786 }
792 LifetimeKind::Param(..) | LifetimeKind::Static => {
793 self.visit_lifetime(&*lifetime);
795 }
796 LifetimeKind::Error => {}
797 }
798 }
799 hir::TyKind::Ref(lifetime_ref, ref mt) => {
800 self.visit_lifetime(lifetime_ref);
801 let scope = Scope::ObjectLifetimeDefault {
802 lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
803 s: self.scope,
804 };
805 self.with(scope, |this| this.visit_ty_unambig(mt.ty));
806 }
807 hir::TyKind::TraitAscription(bounds) => {
808 let scope = Scope::TraitRefBoundary { s: self.scope };
809 self.with(scope, |this| {
810 let scope = Scope::LateBoundary {
811 s: this.scope,
812 what: "`impl Trait` in binding",
813 deny_late_regions: true,
814 };
815 this.with(scope, |this| {
816 for bound in bounds {
817 this.visit_param_bound(bound);
818 }
819 })
820 });
821 }
822 _ => intravisit::walk_ty(self, ty),
823 }
824 }
825
826 #[instrument(level = "debug", skip(self))]
827 fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
828 intravisit::walk_ty_pat(self, p)
829 }
830
831 #[instrument(level = "debug", skip(self))]
832 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
833 use self::hir::TraitItemKind::*;
834 match trait_item.kind {
835 Fn(_, _) => {
836 self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
837 intravisit::walk_trait_item(this, trait_item)
838 });
839 }
840 Type(bounds, ty) => {
841 self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
842 this.visit_generics(trait_item.generics);
843 for bound in bounds {
844 this.visit_param_bound(bound);
845 }
846 if let Some(ty) = ty {
847 this.visit_ty_unambig(ty);
848 }
849 })
850 }
851 Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
852 intravisit::walk_trait_item(this, trait_item)
853 }),
854 }
855 }
856
857 #[instrument(level = "debug", skip(self))]
858 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
859 use self::hir::ImplItemKind::*;
860 match impl_item.kind {
861 Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
862 intravisit::walk_impl_item(this, impl_item)
863 }),
864 Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
865 this.visit_generics(impl_item.generics);
866 this.visit_ty_unambig(ty);
867 }),
868 Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
869 intravisit::walk_impl_item(this, impl_item)
870 }),
871 }
872 }
873
874 #[instrument(level = "debug", skip(self))]
875 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
876 match lifetime_ref.kind {
877 hir::LifetimeKind::Static => {
878 self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
879 }
880 hir::LifetimeKind::Param(param_def_id) => {
881 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
882 }
883 hir::LifetimeKind::Error => {}
885 hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {}
887 }
888 }
889
890 fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
891 for (i, segment) in path.segments.iter().enumerate() {
892 let depth = path.segments.len() - i - 1;
893 if let Some(args) = segment.args {
894 self.visit_segment_args(path.res, depth, args);
895 }
896 }
897 if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
898 self.resolve_type_ref(param_def_id.expect_local(), hir_id);
899 }
900 }
901
902 fn visit_fn(
903 &mut self,
904 fk: intravisit::FnKind<'tcx>,
905 fd: &'tcx hir::FnDecl<'tcx>,
906 body_id: hir::BodyId,
907 _: Span,
908 def_id: LocalDefId,
909 ) {
910 let output = match fd.output {
911 hir::FnRetTy::DefaultReturn(_) => None,
912 hir::FnRetTy::Return(ty) => Some(ty),
913 };
914 if let Some(ty) = output
915 && let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
916 {
917 let bound_vars: Vec<_> =
918 self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
919 let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
920 self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
921 }
922 self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
923 intravisit::walk_fn_kind(self, fk);
924 self.visit_nested_body(body_id)
925 }
926
927 fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
928 let scope = Scope::TraitRefBoundary { s: self.scope };
929 self.with(scope, |this| {
930 walk_list!(this, visit_generic_param, generics.params);
931 walk_list!(this, visit_where_predicate, generics.predicates);
932 })
933 }
934
935 fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
936 let hir_id = predicate.hir_id;
937 match predicate.kind {
938 &hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
939 bounded_ty,
940 bounds,
941 bound_generic_params,
942 origin,
943 ..
944 }) => {
945 let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
946 bound_generic_params
947 .iter()
948 .enumerate()
949 .map(|(late_bound_idx, param)| {
950 (
951 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
952 late_arg_as_bound_arg(param),
953 )
954 })
955 .unzip();
956
957 self.record_late_bound_vars(hir_id, binders);
958
959 self.try_append_return_type_notation_params(hir_id, bounded_ty);
961
962 let scope = Scope::Binder {
967 hir_id,
968 bound_vars,
969 s: self.scope,
970 scope_type: BinderScopeType::Normal,
971 where_bound_origin: Some(origin),
972 };
973 self.with(scope, |this| {
974 walk_list!(this, visit_generic_param, bound_generic_params);
975 this.visit_ty_unambig(bounded_ty);
976 walk_list!(this, visit_param_bound, bounds);
977 })
978 }
979 &hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
980 lifetime,
981 bounds,
982 ..
983 }) => {
984 self.visit_lifetime(lifetime);
985 walk_list!(self, visit_param_bound, bounds);
986 }
987 &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
988 lhs_ty, rhs_ty, ..
989 }) => {
990 self.visit_ty_unambig(lhs_ty);
991 self.visit_ty_unambig(rhs_ty);
992 }
993 }
994 }
995
996 fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
997 self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
998 }
999
1000 fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
1001 self.with(
1002 Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
1003 |this| {
1004 intravisit::walk_anon_const(this, c);
1005 },
1006 );
1007 }
1008
1009 fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
1010 match p.kind {
1011 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1012 self.resolve_type_ref(p.def_id, p.hir_id);
1013 }
1014 GenericParamKind::Lifetime { .. } => {
1015 }
1018 }
1019
1020 match p.kind {
1021 GenericParamKind::Lifetime { .. } => {}
1022 GenericParamKind::Type { default, .. } => {
1023 if let Some(ty) = default {
1024 self.visit_ty_unambig(ty);
1025 }
1026 }
1027 GenericParamKind::Const { ty, default, .. } => {
1028 self.visit_ty_unambig(ty);
1029 if let Some(default) = default {
1030 self.visit_const_arg_unambig(default);
1031 }
1032 }
1033 }
1034 }
1035}
1036
1037fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
1038 debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
1039 let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(param_def_id) else {
1040 bug!("expected GenericParam for object_lifetime_default");
1041 };
1042 match param.source {
1043 hir::GenericParamSource::Generics => {
1044 let parent_def_id = tcx.local_parent(param_def_id);
1045 let generics = tcx.hir_get_generics(parent_def_id).unwrap();
1046 let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1047 let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1048
1049 match param.kind {
1053 GenericParamKind::Type { .. } => {
1054 let mut set = Set1::Empty;
1055
1056 for bound in generics.bounds_for_param(param_def_id) {
1058 if !bound.bound_generic_params.is_empty() {
1061 continue;
1062 }
1063
1064 for bound in bound.bounds {
1065 if let hir::GenericBound::Outlives(lifetime) = bound {
1066 set.insert(lifetime.kind);
1067 }
1068 }
1069 }
1070
1071 match set {
1072 Set1::Empty => ObjectLifetimeDefault::Empty,
1073 Set1::One(hir::LifetimeKind::Static) => ObjectLifetimeDefault::Static,
1074 Set1::One(hir::LifetimeKind::Param(param_def_id)) => {
1075 ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1076 }
1077 _ => ObjectLifetimeDefault::Ambiguous,
1078 }
1079 }
1080 _ => {
1081 bug!("object_lifetime_default_raw must only be called on a type parameter")
1082 }
1083 }
1084 }
1085 hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
1086 }
1087}
1088
1089impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1090 fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1091 where
1092 F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
1093 {
1094 let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
1095 let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
1096 let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
1097 {
1098 let _enter = span.enter();
1099 f(&mut this);
1100 }
1101 }
1102
1103 fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
1104 if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
1105 bug!(
1106 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1107 self.rbv.late_bound_vars[&hir_id.local_id]
1108 )
1109 }
1110 }
1111
1112 fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1131 where
1132 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1133 {
1134 let mut named_late_bound_vars = 0;
1135 let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
1136 .params
1137 .iter()
1138 .map(|param| {
1139 (
1140 param.def_id,
1141 match param.kind {
1142 GenericParamKind::Lifetime { .. } => {
1143 if self.tcx.is_late_bound(param.hir_id) {
1144 let late_bound_idx = named_late_bound_vars;
1145 named_late_bound_vars += 1;
1146 ResolvedArg::late(late_bound_idx, param)
1147 } else {
1148 ResolvedArg::early(param)
1149 }
1150 }
1151 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1152 ResolvedArg::early(param)
1153 }
1154 },
1155 )
1156 })
1157 .collect();
1158
1159 let binders: Vec<_> = generics
1160 .params
1161 .iter()
1162 .filter(|param| {
1163 matches!(param.kind, GenericParamKind::Lifetime { .. })
1164 && self.tcx.is_late_bound(param.hir_id)
1165 })
1166 .map(|param| late_arg_as_bound_arg(param))
1167 .collect();
1168 self.record_late_bound_vars(hir_id, binders);
1169 let scope = Scope::Binder {
1170 hir_id,
1171 bound_vars,
1172 s: self.scope,
1173 scope_type: BinderScopeType::Normal,
1174 where_bound_origin: None,
1175 };
1176 self.with(scope, walk);
1177 }
1178
1179 fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1180 where
1181 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1182 {
1183 let bound_vars =
1184 generics.params.iter().map(|param| (param.def_id, ResolvedArg::early(param))).collect();
1185 self.record_late_bound_vars(hir_id, vec![]);
1186 let scope = Scope::Binder {
1187 hir_id,
1188 bound_vars,
1189 s: self.scope,
1190 scope_type: BinderScopeType::Normal,
1191 where_bound_origin: None,
1192 };
1193 self.with(scope, |this| {
1194 let scope = Scope::TraitRefBoundary { s: this.scope };
1195 this.with(scope, walk)
1196 });
1197 }
1198
1199 #[instrument(level = "debug", skip(self))]
1200 fn resolve_lifetime_ref(
1201 &mut self,
1202 region_def_id: LocalDefId,
1203 lifetime_ref: &'tcx hir::Lifetime,
1204 ) {
1205 let mut late_depth = 0;
1210 let mut scope = self.scope;
1211 let mut outermost_body = None;
1212 let mut crossed_late_boundary = None;
1213 let mut opaque_capture_scopes = vec![];
1214 let result = loop {
1215 match *scope {
1216 Scope::Body { id, s } => {
1217 outermost_body = Some(id);
1218 scope = s;
1219 }
1220
1221 Scope::Root { opt_parent_item } => {
1222 if let Some(parent_item) = opt_parent_item
1223 && let parent_generics = self.tcx.generics_of(parent_item)
1224 && parent_generics
1225 .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
1226 .is_some()
1227 {
1228 break Some(ResolvedArg::EarlyBound(region_def_id));
1229 }
1230 break None;
1231 }
1232
1233 Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1234 if let Some(&def) = bound_vars.get(®ion_def_id) {
1235 break Some(def.shifted(late_depth));
1236 }
1237 match scope_type {
1238 BinderScopeType::Normal => late_depth += 1,
1239 BinderScopeType::Concatenating => {}
1240 }
1241 if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1244 && let hir::LifetimeKind::Param(param_id) = lifetime_ref.kind
1245 && let Some(generics) =
1246 self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
1247 && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1248 && param.is_elided_lifetime()
1249 && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
1250 && !self.tcx.features().anonymous_lifetime_in_impl_trait()
1251 {
1252 let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
1253 &self.tcx.sess,
1254 sym::anonymous_lifetime_in_impl_trait,
1255 lifetime_ref.ident.span,
1256 "anonymous lifetimes in `impl Trait` are unstable",
1257 );
1258
1259 if let Some(generics) =
1260 self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
1261 {
1262 let new_param_sugg =
1263 if let Some(span) = generics.span_for_lifetime_suggestion() {
1264 (span, "'a, ".to_owned())
1265 } else {
1266 (generics.span, "<'a>".to_owned())
1267 };
1268
1269 let lifetime_sugg = lifetime_ref.suggestion("'a");
1270 let suggestions = vec![lifetime_sugg, new_param_sugg];
1271
1272 diag.span_label(
1273 lifetime_ref.ident.span,
1274 "expected named lifetime parameter",
1275 );
1276 diag.multipart_suggestion(
1277 "consider introducing a named lifetime parameter",
1278 suggestions,
1279 rustc_errors::Applicability::MaybeIncorrect,
1280 );
1281 }
1282
1283 diag.emit();
1284 return;
1285 }
1286 scope = s;
1287 }
1288
1289 Scope::Opaque { captures, def_id, s } => {
1290 opaque_capture_scopes.push((def_id, captures));
1291 late_depth = 0;
1292 scope = s;
1293 }
1294
1295 Scope::ObjectLifetimeDefault { s, .. }
1296 | Scope::Supertrait { s, .. }
1297 | Scope::TraitRefBoundary { s, .. } => {
1298 scope = s;
1299 }
1300
1301 Scope::LateBoundary { s, what, deny_late_regions } => {
1302 if deny_late_regions {
1303 crossed_late_boundary = Some(what);
1304 }
1305 scope = s;
1306 }
1307 }
1308 };
1309
1310 if let Some(mut def) = result {
1311 def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
1312
1313 if let ResolvedArg::EarlyBound(..) = def {
1314 } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
1316 && let Some(what) = crossed_late_boundary
1317 {
1318 let use_span = lifetime_ref.ident.span;
1319 let def_span = self.tcx.def_span(param_def_id);
1320 let guar = match self.tcx.def_kind(param_def_id) {
1321 DefKind::LifetimeParam => {
1322 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Lifetime {
1323 use_span,
1324 def_span,
1325 what,
1326 })
1327 }
1328 kind => span_bug!(
1329 use_span,
1330 "did not expect to resolve lifetime to {}",
1331 kind.descr(param_def_id.to_def_id())
1332 ),
1333 };
1334 def = ResolvedArg::Error(guar);
1335 } else if let Some(body_id) = outermost_body {
1336 let fn_id = self.tcx.hir_body_owner(body_id);
1337 match self.tcx.hir_node(fn_id) {
1338 Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
1339 | Node::TraitItem(hir::TraitItem {
1340 owner_id,
1341 kind: hir::TraitItemKind::Fn(..),
1342 ..
1343 })
1344 | Node::ImplItem(hir::ImplItem {
1345 owner_id,
1346 kind: hir::ImplItemKind::Fn(..),
1347 ..
1348 }) => {
1349 def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
1350 }
1351 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1352 def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
1353 }
1354 _ => {}
1355 }
1356 }
1357
1358 self.insert_lifetime(lifetime_ref, def);
1359 return;
1360 }
1361
1362 let mut scope = self.scope;
1372 loop {
1373 match *scope {
1374 Scope::Binder {
1375 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1376 } => {
1377 self.tcx.dcx().emit_err(errors::LateBoundInApit::Lifetime {
1378 span: lifetime_ref.ident.span,
1379 param_span: self.tcx.def_span(region_def_id),
1380 });
1381 return;
1382 }
1383 Scope::Root { .. } => break,
1384 Scope::Binder { s, .. }
1385 | Scope::Body { s, .. }
1386 | Scope::Opaque { s, .. }
1387 | Scope::ObjectLifetimeDefault { s, .. }
1388 | Scope::Supertrait { s, .. }
1389 | Scope::TraitRefBoundary { s, .. }
1390 | Scope::LateBoundary { s, .. } => {
1391 scope = s;
1392 }
1393 }
1394 }
1395
1396 self.tcx.dcx().span_delayed_bug(
1397 lifetime_ref.ident.span,
1398 format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1399 );
1400 }
1401
1402 fn check_lifetime_is_capturable(
1407 &self,
1408 opaque_def_id: LocalDefId,
1409 lifetime: ResolvedArg,
1410 capture_span: Span,
1411 ) -> Result<(), ErrorGuaranteed> {
1412 let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
1413 let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
1414 let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
1415 hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
1418 hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
1420 hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(_), .. }) => {
1421 "higher-ranked lifetime from function pointer"
1422 }
1423 hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
1424 "higher-ranked lifetime from `dyn` type"
1425 }
1426 _ => "higher-ranked lifetime",
1427 };
1428
1429 let decl_span = self.tcx.def_span(lifetime_def_id);
1430 let (span, label) = if capture_span != decl_span {
1431 (capture_span, None)
1432 } else {
1433 let opaque_span = self.tcx.def_span(opaque_def_id);
1434 (opaque_span, Some(opaque_span))
1435 };
1436
1437 let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
1439 span,
1440 label,
1441 decl_span,
1442 bad_place,
1443 });
1444 Err(guar)
1445 }
1446
1447 #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
1448 fn remap_opaque_captures(
1449 &mut self,
1450 opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
1451 mut lifetime: ResolvedArg,
1452 ident: Ident,
1453 ) -> ResolvedArg {
1454 if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
1455 if let Err(guar) =
1456 self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
1457 {
1458 lifetime = ResolvedArg::Error(guar);
1459 }
1460 }
1461
1462 for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
1463 let mut captures = captures.borrow_mut();
1464 let remapped = *captures.entry(lifetime).or_insert_with(|| {
1465 let feed = self.tcx.create_def(
1470 opaque_def_id,
1471 None,
1472 DefKind::LifetimeParam,
1473 Some(DefPathData::OpaqueLifetime(ident.name)),
1474 &mut self.disambiguator,
1475 );
1476 feed.def_span(ident.span);
1477 feed.def_ident_span(Some(ident.span));
1478 feed.def_id()
1479 });
1480 lifetime = ResolvedArg::EarlyBound(remapped);
1481 }
1482 lifetime
1483 }
1484
1485 fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
1486 let mut late_depth = 0;
1491 let mut scope = self.scope;
1492 let mut crossed_late_boundary = None;
1493
1494 let result = loop {
1495 match *scope {
1496 Scope::Body { s, .. } => {
1497 scope = s;
1498 }
1499
1500 Scope::Root { opt_parent_item } => {
1501 if let Some(parent_item) = opt_parent_item
1502 && let parent_generics = self.tcx.generics_of(parent_item)
1503 && parent_generics
1504 .param_def_id_to_index(self.tcx, param_def_id.to_def_id())
1505 .is_some()
1506 {
1507 break Some(ResolvedArg::EarlyBound(param_def_id));
1508 }
1509 break None;
1510 }
1511
1512 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
1513 if let Some(&def) = bound_vars.get(¶m_def_id) {
1514 break Some(def.shifted(late_depth));
1515 }
1516 match scope_type {
1517 BinderScopeType::Normal => late_depth += 1,
1518 BinderScopeType::Concatenating => {}
1519 }
1520 scope = s;
1521 }
1522
1523 Scope::ObjectLifetimeDefault { s, .. }
1524 | Scope::Opaque { s, .. }
1525 | Scope::Supertrait { s, .. }
1526 | Scope::TraitRefBoundary { s, .. } => {
1527 scope = s;
1528 }
1529
1530 Scope::LateBoundary { s, what, deny_late_regions: _ } => {
1531 crossed_late_boundary = Some(what);
1532 scope = s;
1533 }
1534 }
1535 };
1536
1537 if let Some(def) = result {
1538 if let ResolvedArg::LateBound(..) = def
1539 && let Some(what) = crossed_late_boundary
1540 {
1541 let use_span = self.tcx.hir_span(hir_id);
1542 let def_span = self.tcx.def_span(param_def_id);
1543 let guar = match self.tcx.def_kind(param_def_id) {
1544 DefKind::ConstParam => {
1545 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Const {
1546 use_span,
1547 def_span,
1548 what,
1549 })
1550 }
1551 DefKind::TyParam => {
1552 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Type {
1553 use_span,
1554 def_span,
1555 what,
1556 })
1557 }
1558 kind => span_bug!(
1559 use_span,
1560 "did not expect to resolve non-lifetime param to {}",
1561 kind.descr(param_def_id.to_def_id())
1562 ),
1563 };
1564 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1565 } else {
1566 self.rbv.defs.insert(hir_id.local_id, def);
1567 }
1568 return;
1569 }
1570
1571 let mut scope = self.scope;
1581 loop {
1582 match *scope {
1583 Scope::Binder {
1584 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1585 } => {
1586 let guar = self.tcx.dcx().emit_err(match self.tcx.def_kind(param_def_id) {
1587 DefKind::TyParam => errors::LateBoundInApit::Type {
1588 span: self.tcx.hir_span(hir_id),
1589 param_span: self.tcx.def_span(param_def_id),
1590 },
1591 DefKind::ConstParam => errors::LateBoundInApit::Const {
1592 span: self.tcx.hir_span(hir_id),
1593 param_span: self.tcx.def_span(param_def_id),
1594 },
1595 kind => {
1596 bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1597 }
1598 });
1599 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1600 return;
1601 }
1602 Scope::Root { .. } => break,
1603 Scope::Binder { s, .. }
1604 | Scope::Body { s, .. }
1605 | Scope::Opaque { s, .. }
1606 | Scope::ObjectLifetimeDefault { s, .. }
1607 | Scope::Supertrait { s, .. }
1608 | Scope::TraitRefBoundary { s, .. }
1609 | Scope::LateBoundary { s, .. } => {
1610 scope = s;
1611 }
1612 }
1613 }
1614
1615 self.tcx
1616 .dcx()
1617 .span_bug(self.tcx.hir_span(hir_id), format!("could not resolve {param_def_id:?}"));
1618 }
1619
1620 #[instrument(level = "debug", skip(self))]
1621 fn visit_segment_args(
1622 &mut self,
1623 res: Res,
1624 depth: usize,
1625 generic_args: &'tcx hir::GenericArgs<'tcx>,
1626 ) {
1627 if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
1628 self.visit_fn_like_elision(inputs, Some(output), false);
1629 return;
1630 }
1631
1632 for arg in generic_args.args {
1633 if let hir::GenericArg::Lifetime(lt) = arg {
1634 self.visit_lifetime(lt);
1635 }
1636 }
1637
1638 let type_def_id = match res {
1641 Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1642 Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1643 Res::Def(
1644 DefKind::Struct
1645 | DefKind::Union
1646 | DefKind::Enum
1647 | DefKind::TyAlias
1648 | DefKind::Trait,
1649 def_id,
1650 ) if depth == 0 => Some(def_id),
1651 _ => None,
1652 };
1653
1654 debug!(?type_def_id);
1655
1656 let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1672 let in_body = {
1673 let mut scope = self.scope;
1674 loop {
1675 match *scope {
1676 Scope::Root { .. } => break false,
1677
1678 Scope::Body { .. } => break true,
1679
1680 Scope::Binder { s, .. }
1681 | Scope::ObjectLifetimeDefault { s, .. }
1682 | Scope::Opaque { s, .. }
1683 | Scope::Supertrait { s, .. }
1684 | Scope::TraitRefBoundary { s, .. }
1685 | Scope::LateBoundary { s, .. } => {
1686 scope = s;
1687 }
1688 }
1689 }
1690 };
1691
1692 let rbv = &self.rbv;
1693 let generics = self.tcx.generics_of(def_id);
1694
1695 debug_assert_eq!(generics.parent_count, 0);
1697
1698 let set_to_region = |set: ObjectLifetimeDefault| match set {
1699 ObjectLifetimeDefault::Empty => {
1700 if in_body {
1701 None
1702 } else {
1703 Some(ResolvedArg::StaticLifetime)
1704 }
1705 }
1706 ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
1707 ObjectLifetimeDefault::Param(param_def_id) => {
1708 let index = generics.param_def_id_to_index[¶m_def_id] as usize;
1710 generic_args.args.get(index).and_then(|arg| match arg {
1711 GenericArg::Lifetime(lt) => rbv.defs.get(<.hir_id.local_id).copied(),
1712 _ => None,
1713 })
1714 }
1715 ObjectLifetimeDefault::Ambiguous => None,
1716 };
1717 generics
1718 .own_params
1719 .iter()
1720 .filter_map(|param| {
1721 match self.tcx.def_kind(param.def_id) {
1722 DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1727 DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1728 DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1731 dk => bug!("unexpected def_kind {:?}", dk),
1732 }
1733 })
1734 .map(set_to_region)
1735 .collect()
1736 });
1737
1738 debug!(?object_lifetime_defaults);
1739
1740 let mut i = 0;
1741 for arg in generic_args.args {
1742 match arg {
1743 GenericArg::Lifetime(_) => {}
1744 GenericArg::Type(ty) => {
1745 if let Some(<) = object_lifetime_defaults.get(i) {
1746 let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1747 self.with(scope, |this| this.visit_ty(ty));
1748 } else {
1749 self.visit_ty(ty);
1750 }
1751 i += 1;
1752 }
1753 GenericArg::Const(ct) => {
1754 self.visit_const_arg(ct);
1755 i += 1;
1756 }
1757 GenericArg::Infer(inf) => {
1758 self.visit_id(inf.hir_id);
1759 i += 1;
1760 }
1761 }
1762 }
1763
1764 let has_lifetime_parameter =
1789 generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1790
1791 for constraint in generic_args.constraints {
1794 let scope = Scope::ObjectLifetimeDefault {
1795 lifetime: if has_lifetime_parameter {
1796 None
1797 } else {
1798 Some(ResolvedArg::StaticLifetime)
1799 },
1800 s: self.scope,
1801 };
1802 if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
1816 {
1817 let bound_vars = if let Some(type_def_id) = type_def_id
1818 && self.tcx.def_kind(type_def_id) == DefKind::Trait
1819 && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
1820 self.tcx,
1821 type_def_id,
1822 constraint.ident,
1823 ty::AssocTag::Fn,
1824 ) {
1825 bound_vars.extend(
1826 self.tcx
1827 .generics_of(assoc_fn.def_id)
1828 .own_params
1829 .iter()
1830 .map(|param| generic_param_def_as_bound_arg(param)),
1831 );
1832 bound_vars.extend(
1833 self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars(),
1834 );
1835 bound_vars
1836 } else {
1837 self.tcx
1838 .dcx()
1839 .span_delayed_bug(constraint.ident.span, "bad return type notation here");
1840 vec![]
1841 };
1842 self.with(scope, |this| {
1843 let scope = Scope::Supertrait { bound_vars, s: this.scope };
1844 this.with(scope, |this| {
1845 let (bound_vars, _) = this.poly_trait_ref_binder_info();
1846 this.record_late_bound_vars(constraint.hir_id, bound_vars);
1847 this.visit_assoc_item_constraint(constraint)
1848 });
1849 });
1850 } else if let Some(type_def_id) = type_def_id {
1851 let bound_vars = BoundVarContext::supertrait_hrtb_vars(
1852 self.tcx,
1853 type_def_id,
1854 constraint.ident,
1855 ty::AssocTag::Type,
1856 )
1857 .map(|(bound_vars, _)| bound_vars);
1858 self.with(scope, |this| {
1859 let scope = Scope::Supertrait {
1860 bound_vars: bound_vars.unwrap_or_default(),
1861 s: this.scope,
1862 };
1863 this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1864 });
1865 } else {
1866 self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1867 }
1868 }
1869 }
1870
1871 fn supertrait_hrtb_vars(
1884 tcx: TyCtxt<'tcx>,
1885 def_id: DefId,
1886 assoc_ident: Ident,
1887 assoc_tag: ty::AssocTag,
1888 ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
1889 let trait_defines_associated_item_named = |trait_def_id: DefId| {
1890 tcx.associated_items(trait_def_id).find_by_ident_and_kind(
1891 tcx,
1892 assoc_ident,
1893 assoc_tag,
1894 trait_def_id,
1895 )
1896 };
1897
1898 use smallvec::{SmallVec, smallvec};
1899 let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1900 smallvec![(def_id, smallvec![])];
1901 let mut visited: FxHashSet<DefId> = FxHashSet::default();
1902 loop {
1903 let Some((def_id, bound_vars)) = stack.pop() else {
1904 break None;
1905 };
1906 match tcx.def_kind(def_id) {
1909 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
1910 _ => break None,
1911 }
1912
1913 if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
1914 break Some((bound_vars.into_iter().collect(), assoc_item));
1915 }
1916 let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_ident));
1917 let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| {
1918 let bound_predicate = pred.kind();
1919 match bound_predicate.skip_binder() {
1920 ty::ClauseKind::Trait(data) => {
1921 let pred_bound_vars = bound_predicate.bound_vars();
1924 let mut all_bound_vars = bound_vars.clone();
1925 all_bound_vars.extend(pred_bound_vars.iter());
1926 let super_def_id = data.trait_ref.def_id;
1927 Some((super_def_id, all_bound_vars))
1928 }
1929 _ => None,
1930 }
1931 });
1932
1933 let obligations = obligations.filter(|o| visited.insert(o.0));
1934 stack.extend(obligations);
1935 }
1936 }
1937
1938 #[instrument(level = "debug", skip(self))]
1939 fn visit_fn_like_elision(
1940 &mut self,
1941 inputs: &'tcx [hir::Ty<'tcx>],
1942 output: Option<&'tcx hir::Ty<'tcx>>,
1943 in_closure: bool,
1944 ) {
1945 self.with(
1946 Scope::ObjectLifetimeDefault {
1947 lifetime: Some(ResolvedArg::StaticLifetime),
1948 s: self.scope,
1949 },
1950 |this| {
1951 for input in inputs {
1952 this.visit_ty_unambig(input);
1953 }
1954 if !in_closure && let Some(output) = output {
1955 this.visit_ty_unambig(output);
1956 }
1957 },
1958 );
1959 if in_closure && let Some(output) = output {
1960 self.visit_ty_unambig(output);
1961 }
1962 }
1963
1964 #[instrument(level = "debug", skip(self))]
1965 fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1966 let mut late_depth = 0;
1967 let mut scope = self.scope;
1968 let mut opaque_capture_scopes = vec![];
1969 let mut lifetime = loop {
1970 match *scope {
1971 Scope::Binder { s, scope_type, .. } => {
1972 match scope_type {
1973 BinderScopeType::Normal => late_depth += 1,
1974 BinderScopeType::Concatenating => {}
1975 }
1976 scope = s;
1977 }
1978
1979 Scope::Root { .. } => break ResolvedArg::StaticLifetime,
1980
1981 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1982
1983 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
1984 break l.shifted(late_depth);
1985 }
1986
1987 Scope::Opaque { captures, def_id, s } => {
1988 opaque_capture_scopes.push((def_id, captures));
1989 late_depth = 0;
1990 scope = s;
1991 }
1992
1993 Scope::Supertrait { s, .. }
1994 | Scope::TraitRefBoundary { s, .. }
1995 | Scope::LateBoundary { s, .. } => {
1996 scope = s;
1997 }
1998 }
1999 };
2000
2001 lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
2002
2003 self.insert_lifetime(lifetime_ref, lifetime);
2004 }
2005
2006 #[instrument(level = "debug", skip(self))]
2007 fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
2008 debug!(span = ?lifetime_ref.ident.span);
2009 self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
2010 }
2011
2012 fn try_append_return_type_notation_params(
2031 &mut self,
2032 hir_id: HirId,
2033 hir_ty: &'tcx hir::Ty<'tcx>,
2034 ) {
2035 let hir::TyKind::Path(qpath) = hir_ty.kind else {
2036 return;
2040 };
2041
2042 let (mut bound_vars, item_def_id, item_segment) = match qpath {
2043 hir::QPath::Resolved(_, path)
2045 if let [.., item_segment] = &path.segments[..]
2046 && item_segment.args.is_some_and(|args| {
2047 matches!(
2048 args.parenthesized,
2049 hir::GenericArgsParentheses::ReturnTypeNotation
2050 )
2051 }) =>
2052 {
2053 match path.res {
2054 Res::Err => return,
2055 Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
2056 _ => bug!("only expected method resolution for fully qualified RTN"),
2057 }
2058 }
2059
2060 hir::QPath::TypeRelative(qself, item_segment)
2062 if item_segment.args.is_some_and(|args| {
2063 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2064 }) =>
2065 {
2066 let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
2069 return;
2070 };
2071 match path.res {
2072 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
2073 let mut bounds =
2074 self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
2075 BoundVarContext::supertrait_hrtb_vars(
2076 self.tcx,
2077 trait_def_id,
2078 item_segment.ident,
2079 ty::AssocTag::Fn,
2080 )
2081 });
2082
2083 let Some((bound_vars, assoc_item)) = bounds.next() else {
2084 self.tcx
2086 .dcx()
2087 .span_delayed_bug(path.span, "no resolution for RTN path");
2088 return;
2089 };
2090
2091 for (second_vars, second_assoc_item) in bounds {
2094 if second_vars != bound_vars || second_assoc_item != assoc_item {
2095 self.tcx.dcx().span_delayed_bug(
2097 path.span,
2098 "ambiguous resolution for RTN path",
2099 );
2100 return;
2101 }
2102 }
2103
2104 (bound_vars, assoc_item.def_id, item_segment)
2105 }
2106 Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
2109 let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self
2110 .tcx
2111 .hir_node_by_def_id(impl_def_id.expect_local())
2112 .expect_item()
2113 .kind
2114 else {
2115 return;
2116 };
2117 let Some(trait_def_id) = trait_ref.trait_def_id() else {
2118 return;
2119 };
2120 let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
2121 self.tcx,
2122 trait_def_id,
2123 item_segment.ident,
2124 ty::AssocTag::Fn,
2125 ) else {
2126 return;
2127 };
2128 (bound_vars, assoc_item.def_id, item_segment)
2129 }
2130 _ => return,
2131 }
2132 }
2133
2134 _ => return,
2135 };
2136
2137 bound_vars.extend(
2141 self.tcx
2142 .generics_of(item_def_id)
2143 .own_params
2144 .iter()
2145 .map(|param| generic_param_def_as_bound_arg(param)),
2146 );
2147 bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
2148
2149 let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
2165 let existing_bound_vars_saved = existing_bound_vars.clone();
2166 existing_bound_vars.extend(bound_vars);
2167 self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
2168 }
2169
2170 fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
2173 gen move {
2174 let mut scope = self.scope;
2175 loop {
2176 let hir_id = match *scope {
2177 Scope::Binder { hir_id, .. } => Some(hir_id),
2178 Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2179 Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2180 }
2181 Scope::Body { .. }
2182 | Scope::ObjectLifetimeDefault { .. }
2183 | Scope::Supertrait { .. }
2184 | Scope::TraitRefBoundary { .. }
2185 | Scope::LateBoundary { .. }
2186 | Scope::Opaque { .. }
2187 | Scope::Root { opt_parent_item: None } => None,
2188 };
2189
2190 if let Some(hir_id) = hir_id {
2191 let node = self.tcx.hir_node(hir_id);
2192 if let Res::SelfTyParam { trait_: _ } = expected_res
2196 && let hir::Node::Item(item) = node
2197 && let hir::ItemKind::Trait(..) = item.kind
2198 {
2199 yield item.owner_id.def_id.to_def_id();
2202 } else if let Some(generics) = node.generics() {
2203 for pred in generics.predicates {
2204 let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
2205 continue;
2206 };
2207 let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2208 pred.bounded_ty.kind
2209 else {
2210 continue;
2211 };
2212 if bounded_path.res != expected_res {
2214 continue;
2215 }
2216 for pred in pred.bounds {
2217 match pred {
2218 hir::GenericBound::Trait(poly_trait_ref) => {
2219 if let Some(def_id) =
2220 poly_trait_ref.trait_ref.trait_def_id()
2221 {
2222 yield def_id;
2223 }
2224 }
2225 hir::GenericBound::Outlives(_)
2226 | hir::GenericBound::Use(_, _) => {}
2227 }
2228 }
2229 }
2230 }
2231 }
2232
2233 match *scope {
2234 Scope::Binder { s, .. }
2235 | Scope::Body { s, .. }
2236 | Scope::ObjectLifetimeDefault { s, .. }
2237 | Scope::Supertrait { s, .. }
2238 | Scope::TraitRefBoundary { s }
2239 | Scope::LateBoundary { s, .. }
2240 | Scope::Opaque { s, .. } => {
2241 scope = s;
2242 }
2243 Scope::Root { .. } => break,
2244 }
2245 }
2246 }
2247 }
2248}
2249
2250fn is_late_bound_map(
2261 tcx: TyCtxt<'_>,
2262 owner_id: hir::OwnerId,
2263) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2264 let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?;
2265 let generics = tcx.hir_get_generics(owner_id.def_id)?;
2266
2267 let mut late_bound = FxIndexSet::default();
2268
2269 let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2270 for arg_ty in sig.decl.inputs {
2271 constrained_by_input.visit_ty_unambig(arg_ty);
2272 }
2273
2274 let mut appears_in_output =
2275 AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
2276 intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2277 if appears_in_output.has_fully_capturing_opaque {
2278 appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2279 }
2280
2281 debug!(?constrained_by_input.regions);
2282
2283 let mut appears_in_where_clause =
2288 AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
2289 appears_in_where_clause.visit_generics(generics);
2290 debug!(?appears_in_where_clause.regions);
2291
2292 for param in generics.params {
2297 match param.kind {
2298 hir::GenericParamKind::Lifetime { .. } => { }
2299
2300 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2302 }
2303
2304 if appears_in_where_clause.regions.contains(¶m.def_id) {
2306 continue;
2307 }
2308
2309 if !constrained_by_input.regions.contains(¶m.def_id)
2311 && appears_in_output.regions.contains(¶m.def_id)
2312 {
2313 continue;
2314 }
2315
2316 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2317
2318 let inserted = late_bound.insert(param.hir_id.local_id);
2319 assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2320 }
2321
2322 debug!(?late_bound);
2323 return Some(tcx.arena.alloc(late_bound));
2324
2325 struct ConstrainedCollectorPostHirTyLowering {
2347 arg_is_constrained: Box<[bool]>,
2348 }
2349
2350 use ty::Ty;
2351 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2352 fn visit_ty(&mut self, t: Ty<'tcx>) {
2353 match t.kind() {
2354 ty::Param(param_ty) => {
2355 self.arg_is_constrained[param_ty.index as usize] = true;
2356 }
2357 ty::Alias(ty::Projection | ty::Inherent, _) => return,
2358 _ => (),
2359 }
2360 t.super_visit_with(self)
2361 }
2362
2363 fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2364
2365 fn visit_region(&mut self, r: ty::Region<'tcx>) {
2366 debug!("r={:?}", r.kind());
2367 if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2368 self.arg_is_constrained[region.index as usize] = true;
2369 }
2370 }
2371 }
2372
2373 struct ConstrainedCollector<'tcx> {
2374 tcx: TyCtxt<'tcx>,
2375 regions: FxHashSet<LocalDefId>,
2376 }
2377
2378 impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2379 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2380 match ty.kind {
2381 hir::TyKind::Path(
2382 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2383 ) => {
2384 }
2388
2389 hir::TyKind::Path(hir::QPath::Resolved(
2390 None,
2391 hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2392 )) => {
2393 let generics = self.tcx.generics_of(alias_def);
2396 let mut walker = ConstrainedCollectorPostHirTyLowering {
2397 arg_is_constrained: vec![false; generics.own_params.len()]
2398 .into_boxed_slice(),
2399 };
2400 walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2401
2402 match segments.last() {
2403 Some(hir::PathSegment { args: Some(args), .. }) => {
2404 let tcx = self.tcx;
2405 for constrained_arg in
2406 args.args.iter().enumerate().flat_map(|(n, arg)| {
2407 match walker.arg_is_constrained.get(n) {
2408 Some(true) => Some(arg),
2409 Some(false) => None,
2410 None => {
2411 tcx.dcx().span_delayed_bug(
2412 *span,
2413 format!(
2414 "Incorrect generic arg count for alias {alias_def:?}"
2415 ),
2416 );
2417 None
2418 }
2419 }
2420 })
2421 {
2422 self.visit_generic_arg(constrained_arg);
2423 }
2424 }
2425 Some(_) => (),
2426 None => bug!("Path with no segments or self type"),
2427 }
2428 }
2429
2430 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2431 if let Some(last_segment) = path.segments.last() {
2437 self.visit_path_segment(last_segment);
2438 }
2439 }
2440
2441 _ => {
2442 intravisit::walk_ty(self, ty);
2443 }
2444 }
2445 }
2446
2447 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2448 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2449 self.regions.insert(def_id);
2450 }
2451 }
2452 }
2453
2454 struct AllCollector {
2455 has_fully_capturing_opaque: bool,
2456 regions: FxHashSet<LocalDefId>,
2457 }
2458
2459 impl<'tcx> Visitor<'tcx> for AllCollector {
2460 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2461 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2462 self.regions.insert(def_id);
2463 }
2464 }
2465
2466 fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
2467 if !self.has_fully_capturing_opaque {
2468 self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
2469 }
2470 intravisit::walk_opaque_ty(self, opaque);
2471 }
2472 }
2473}
2474
2475fn deny_non_region_late_bound(
2476 tcx: TyCtxt<'_>,
2477 bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2478 where_: &str,
2479) {
2480 let mut first = true;
2481
2482 for (var, arg) in bound_vars {
2483 let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2484 span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2485 };
2486
2487 let what = match param.kind {
2488 hir::GenericParamKind::Type { .. } => "type",
2489 hir::GenericParamKind::Const { .. } => "const",
2490 hir::GenericParamKind::Lifetime { .. } => continue,
2491 };
2492
2493 let diag = tcx.dcx().struct_span_err(
2494 param.span,
2495 format!("late-bound {what} parameter not allowed on {where_}"),
2496 );
2497
2498 let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
2499
2500 first = false;
2501 *arg = ResolvedArg::Error(guar);
2502 }
2503}