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 if let hir::ItemKind::Impl(impl_) = item.kind
608 && let Some(of_trait) = impl_.of_trait
609 {
610 self.record_late_bound_vars(of_trait.trait_ref.hir_ref_id, Vec::default());
611 }
612 match item.kind {
613 hir::ItemKind::Fn { generics, .. } => {
614 self.visit_early_late(item.hir_id(), generics, |this| {
615 intravisit::walk_item(this, item);
616 });
617 }
618
619 hir::ItemKind::ExternCrate(..)
620 | hir::ItemKind::Use(..)
621 | hir::ItemKind::Macro(..)
622 | hir::ItemKind::Mod(..)
623 | hir::ItemKind::ForeignMod { .. }
624 | hir::ItemKind::Static(..)
625 | hir::ItemKind::GlobalAsm { .. } => {
626 intravisit::walk_item(self, item);
628 }
629 hir::ItemKind::TyAlias(_, generics, _)
630 | hir::ItemKind::Const(_, generics, _, _)
631 | hir::ItemKind::Enum(_, generics, _)
632 | hir::ItemKind::Struct(_, generics, _)
633 | hir::ItemKind::Union(_, generics, _)
634 | hir::ItemKind::Trait(_, _, _, _, generics, ..)
635 | hir::ItemKind::TraitAlias(_, generics, ..)
636 | hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
637 self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
639 }
640 }
641 }
642
643 fn visit_precise_capturing_arg(
644 &mut self,
645 arg: &'tcx hir::PreciseCapturingArg<'tcx>,
646 ) -> Self::Result {
647 match *arg {
648 hir::PreciseCapturingArg::Lifetime(lt) => match lt.kind {
649 LifetimeKind::Param(def_id) => {
650 self.resolve_lifetime_ref(def_id, lt);
651 }
652 LifetimeKind::Error => {}
653 LifetimeKind::ImplicitObjectLifetimeDefault
654 | LifetimeKind::Infer
655 | LifetimeKind::Static => {
656 self.tcx.dcx().emit_err(errors::BadPreciseCapture {
657 span: lt.ident.span,
658 kind: "lifetime",
659 found: format!("`{}`", lt.ident.name),
660 });
661 }
662 },
663 hir::PreciseCapturingArg::Param(param) => match param.res {
664 Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
665 | Res::SelfTyParam { trait_: def_id } => {
666 self.resolve_type_ref(def_id.expect_local(), param.hir_id);
667 }
668 Res::SelfTyAlias { alias_to, .. } => {
669 self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
670 span: param.ident.span,
671 self_span: self.tcx.def_span(alias_to),
672 what: self.tcx.def_descr(alias_to),
673 });
674 }
675 res => {
676 self.tcx.dcx().span_delayed_bug(
677 param.ident.span,
678 format!("expected type or const param, found {res:?}"),
679 );
680 }
681 },
682 }
683 }
684
685 fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
686 match item.kind {
687 hir::ForeignItemKind::Fn(_, _, generics) => {
688 self.visit_early_late(item.hir_id(), generics, |this| {
689 intravisit::walk_foreign_item(this, item);
690 })
691 }
692 hir::ForeignItemKind::Static(..) => {
693 intravisit::walk_foreign_item(self, item);
694 }
695 hir::ForeignItemKind::Type => {
696 intravisit::walk_foreign_item(self, item);
697 }
698 }
699 }
700
701 #[instrument(level = "debug", skip(self))]
702 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
703 match ty.kind {
704 hir::TyKind::FnPtr(c) => {
705 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
706 .generic_params
707 .iter()
708 .enumerate()
709 .map(|(late_bound_idx, param)| {
710 (
711 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
712 late_arg_as_bound_arg(param),
713 )
714 })
715 .unzip();
716
717 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
718
719 self.record_late_bound_vars(ty.hir_id, binders);
720 let scope = Scope::Binder {
721 hir_id: ty.hir_id,
722 bound_vars,
723 s: self.scope,
724 scope_type: BinderScopeType::Normal,
725 where_bound_origin: None,
726 };
727 self.with(scope, |this| {
728 intravisit::walk_ty(this, ty);
730 });
731 }
732 hir::TyKind::UnsafeBinder(binder) => {
733 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
734 binder
735 .generic_params
736 .iter()
737 .enumerate()
738 .map(|(late_bound_idx, param)| {
739 (
740 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
741 late_arg_as_bound_arg(param),
742 )
743 })
744 .unzip();
745
746 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
747
748 self.record_late_bound_vars(ty.hir_id, binders);
749 let scope = Scope::Binder {
750 hir_id: ty.hir_id,
751 bound_vars,
752 s: self.scope,
753 scope_type: BinderScopeType::Normal,
754 where_bound_origin: None,
755 };
756 self.with(scope, |this| {
757 intravisit::walk_ty(this, ty);
759 });
760 }
761 hir::TyKind::TraitObject(bounds, lifetime) => {
762 let lifetime = lifetime.pointer();
763
764 debug!(?bounds, ?lifetime, "TraitObject");
765 let scope = Scope::TraitRefBoundary { s: self.scope };
766 self.with(scope, |this| {
767 for bound in bounds {
768 this.visit_poly_trait_ref_inner(
769 bound,
770 NonLifetimeBinderAllowed::Deny("trait object types"),
771 );
772 }
773 });
774 match lifetime.kind {
775 LifetimeKind::ImplicitObjectLifetimeDefault => {
776 self.resolve_object_lifetime_default(&*lifetime)
781 }
782 LifetimeKind::Infer => {
783 }
789 LifetimeKind::Param(..) | LifetimeKind::Static => {
790 self.visit_lifetime(&*lifetime);
792 }
793 LifetimeKind::Error => {}
794 }
795 }
796 hir::TyKind::Ref(lifetime_ref, ref mt) => {
797 self.visit_lifetime(lifetime_ref);
798 let scope = Scope::ObjectLifetimeDefault {
799 lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
800 s: self.scope,
801 };
802 self.with(scope, |this| this.visit_ty_unambig(mt.ty));
803 }
804 hir::TyKind::TraitAscription(bounds) => {
805 let scope = Scope::TraitRefBoundary { s: self.scope };
806 self.with(scope, |this| {
807 let scope = Scope::LateBoundary {
808 s: this.scope,
809 what: "`impl Trait` in binding",
810 deny_late_regions: true,
811 };
812 this.with(scope, |this| {
813 for bound in bounds {
814 this.visit_param_bound(bound);
815 }
816 })
817 });
818 }
819 _ => intravisit::walk_ty(self, ty),
820 }
821 }
822
823 #[instrument(level = "debug", skip(self))]
824 fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
825 intravisit::walk_ty_pat(self, p)
826 }
827
828 #[instrument(level = "debug", skip(self))]
829 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
830 use self::hir::TraitItemKind::*;
831 match trait_item.kind {
832 Fn(_, _) => {
833 self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
834 intravisit::walk_trait_item(this, trait_item)
835 });
836 }
837 Type(bounds, ty) => {
838 self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
839 this.visit_generics(trait_item.generics);
840 for bound in bounds {
841 this.visit_param_bound(bound);
842 }
843 if let Some(ty) = ty {
844 this.visit_ty_unambig(ty);
845 }
846 })
847 }
848 Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
849 intravisit::walk_trait_item(this, trait_item)
850 }),
851 }
852 }
853
854 #[instrument(level = "debug", skip(self))]
855 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
856 use self::hir::ImplItemKind::*;
857 match impl_item.kind {
858 Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
859 intravisit::walk_impl_item(this, impl_item)
860 }),
861 Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
862 this.visit_generics(impl_item.generics);
863 this.visit_ty_unambig(ty);
864 }),
865 Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
866 intravisit::walk_impl_item(this, impl_item)
867 }),
868 }
869 }
870
871 #[instrument(level = "debug", skip(self))]
872 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
873 match lifetime_ref.kind {
874 hir::LifetimeKind::Static => {
875 self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
876 }
877 hir::LifetimeKind::Param(param_def_id) => {
878 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
879 }
880 hir::LifetimeKind::Error => {}
882 hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {}
884 }
885 }
886
887 fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: HirId) {
888 for (i, segment) in path.segments.iter().enumerate() {
889 let depth = path.segments.len() - i - 1;
890 if let Some(args) = segment.args {
891 self.visit_segment_args(path.res, depth, args);
892 }
893 }
894 if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
895 self.resolve_type_ref(param_def_id.expect_local(), hir_id);
896 }
897 }
898
899 fn visit_fn(
900 &mut self,
901 fk: intravisit::FnKind<'tcx>,
902 fd: &'tcx hir::FnDecl<'tcx>,
903 body_id: hir::BodyId,
904 _: Span,
905 def_id: LocalDefId,
906 ) {
907 let output = match fd.output {
908 hir::FnRetTy::DefaultReturn(_) => None,
909 hir::FnRetTy::Return(ty) => Some(ty),
910 };
911 if let Some(ty) = output
912 && let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
913 {
914 let bound_vars: Vec<_> =
915 self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
916 let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
917 self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
918 }
919 self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
920 intravisit::walk_fn_kind(self, fk);
921 self.visit_nested_body(body_id)
922 }
923
924 fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
925 let scope = Scope::TraitRefBoundary { s: self.scope };
926 self.with(scope, |this| {
927 walk_list!(this, visit_generic_param, generics.params);
928 walk_list!(this, visit_where_predicate, generics.predicates);
929 })
930 }
931
932 fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
933 let hir_id = predicate.hir_id;
934 match predicate.kind {
935 &hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
936 bounded_ty,
937 bounds,
938 bound_generic_params,
939 origin,
940 ..
941 }) => {
942 let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
943 bound_generic_params
944 .iter()
945 .enumerate()
946 .map(|(late_bound_idx, param)| {
947 (
948 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
949 late_arg_as_bound_arg(param),
950 )
951 })
952 .unzip();
953
954 self.record_late_bound_vars(hir_id, binders);
955
956 self.try_append_return_type_notation_params(hir_id, bounded_ty);
958
959 let scope = Scope::Binder {
964 hir_id,
965 bound_vars,
966 s: self.scope,
967 scope_type: BinderScopeType::Normal,
968 where_bound_origin: Some(origin),
969 };
970 self.with(scope, |this| {
971 walk_list!(this, visit_generic_param, bound_generic_params);
972 this.visit_ty_unambig(bounded_ty);
973 walk_list!(this, visit_param_bound, bounds);
974 })
975 }
976 &hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
977 lifetime,
978 bounds,
979 ..
980 }) => {
981 self.visit_lifetime(lifetime);
982 walk_list!(self, visit_param_bound, bounds);
983 }
984 &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
985 lhs_ty, rhs_ty, ..
986 }) => {
987 self.visit_ty_unambig(lhs_ty);
988 self.visit_ty_unambig(rhs_ty);
989 }
990 }
991 }
992
993 fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
994 self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
995 }
996
997 fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
998 self.with(
999 Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
1000 |this| {
1001 intravisit::walk_anon_const(this, c);
1002 },
1003 );
1004 }
1005
1006 fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
1007 match p.kind {
1008 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1009 self.resolve_type_ref(p.def_id, p.hir_id);
1010 }
1011 GenericParamKind::Lifetime { .. } => {
1012 }
1015 }
1016
1017 match p.kind {
1018 GenericParamKind::Lifetime { .. } => {}
1019 GenericParamKind::Type { default, .. } => {
1020 if let Some(ty) = default {
1021 self.visit_ty_unambig(ty);
1022 }
1023 }
1024 GenericParamKind::Const { ty, default, .. } => {
1025 self.visit_ty_unambig(ty);
1026 if let Some(default) = default {
1027 self.visit_const_arg_unambig(default);
1028 }
1029 }
1030 }
1031 }
1032}
1033
1034fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
1035 debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
1036 let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(param_def_id) else {
1037 bug!("expected GenericParam for object_lifetime_default");
1038 };
1039 match param.source {
1040 hir::GenericParamSource::Generics => {
1041 let parent_def_id = tcx.local_parent(param_def_id);
1042 let generics = tcx.hir_get_generics(parent_def_id).unwrap();
1043 let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
1044 let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
1045
1046 match param.kind {
1050 GenericParamKind::Type { .. } => {
1051 let mut set = Set1::Empty;
1052
1053 for bound in generics.bounds_for_param(param_def_id) {
1055 if !bound.bound_generic_params.is_empty() {
1058 continue;
1059 }
1060
1061 for bound in bound.bounds {
1062 if let hir::GenericBound::Outlives(lifetime) = bound {
1063 set.insert(lifetime.kind);
1064 }
1065 }
1066 }
1067
1068 match set {
1069 Set1::Empty => ObjectLifetimeDefault::Empty,
1070 Set1::One(hir::LifetimeKind::Static) => ObjectLifetimeDefault::Static,
1071 Set1::One(hir::LifetimeKind::Param(param_def_id)) => {
1072 ObjectLifetimeDefault::Param(param_def_id.to_def_id())
1073 }
1074 _ => ObjectLifetimeDefault::Ambiguous,
1075 }
1076 }
1077 _ => {
1078 bug!("object_lifetime_default_raw must only be called on a type parameter")
1079 }
1080 }
1081 }
1082 hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
1083 }
1084}
1085
1086impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
1087 fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
1088 where
1089 F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
1090 {
1091 let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
1092 let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
1093 let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
1094 {
1095 let _enter = span.enter();
1096 f(&mut this);
1097 }
1098 }
1099
1100 fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
1101 if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
1102 bug!(
1103 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1104 self.rbv.late_bound_vars[&hir_id.local_id]
1105 )
1106 }
1107 }
1108
1109 fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1128 where
1129 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1130 {
1131 let mut named_late_bound_vars = 0;
1132 let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
1133 .params
1134 .iter()
1135 .map(|param| {
1136 (
1137 param.def_id,
1138 match param.kind {
1139 GenericParamKind::Lifetime { .. } => {
1140 if self.tcx.is_late_bound(param.hir_id) {
1141 let late_bound_idx = named_late_bound_vars;
1142 named_late_bound_vars += 1;
1143 ResolvedArg::late(late_bound_idx, param)
1144 } else {
1145 ResolvedArg::early(param)
1146 }
1147 }
1148 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1149 ResolvedArg::early(param)
1150 }
1151 },
1152 )
1153 })
1154 .collect();
1155
1156 let binders: Vec<_> = generics
1157 .params
1158 .iter()
1159 .filter(|param| {
1160 matches!(param.kind, GenericParamKind::Lifetime { .. })
1161 && self.tcx.is_late_bound(param.hir_id)
1162 })
1163 .map(|param| late_arg_as_bound_arg(param))
1164 .collect();
1165 self.record_late_bound_vars(hir_id, binders);
1166 let scope = Scope::Binder {
1167 hir_id,
1168 bound_vars,
1169 s: self.scope,
1170 scope_type: BinderScopeType::Normal,
1171 where_bound_origin: None,
1172 };
1173 self.with(scope, walk);
1174 }
1175
1176 fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1177 where
1178 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1179 {
1180 let bound_vars =
1181 generics.params.iter().map(|param| (param.def_id, ResolvedArg::early(param))).collect();
1182 self.record_late_bound_vars(hir_id, vec![]);
1183 let scope = Scope::Binder {
1184 hir_id,
1185 bound_vars,
1186 s: self.scope,
1187 scope_type: BinderScopeType::Normal,
1188 where_bound_origin: None,
1189 };
1190 self.with(scope, |this| {
1191 let scope = Scope::TraitRefBoundary { s: this.scope };
1192 this.with(scope, walk)
1193 });
1194 }
1195
1196 #[instrument(level = "debug", skip(self))]
1197 fn resolve_lifetime_ref(
1198 &mut self,
1199 region_def_id: LocalDefId,
1200 lifetime_ref: &'tcx hir::Lifetime,
1201 ) {
1202 let mut late_depth = 0;
1207 let mut scope = self.scope;
1208 let mut outermost_body = None;
1209 let mut crossed_late_boundary = None;
1210 let mut opaque_capture_scopes = vec![];
1211 let result = loop {
1212 match *scope {
1213 Scope::Body { id, s } => {
1214 outermost_body = Some(id);
1215 scope = s;
1216 }
1217
1218 Scope::Root { opt_parent_item } => {
1219 if let Some(parent_item) = opt_parent_item
1220 && let parent_generics = self.tcx.generics_of(parent_item)
1221 && parent_generics
1222 .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
1223 .is_some()
1224 {
1225 break Some(ResolvedArg::EarlyBound(region_def_id));
1226 }
1227 break None;
1228 }
1229
1230 Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1231 if let Some(&def) = bound_vars.get(®ion_def_id) {
1232 break Some(def.shifted(late_depth));
1233 }
1234 match scope_type {
1235 BinderScopeType::Normal => late_depth += 1,
1236 BinderScopeType::Concatenating => {}
1237 }
1238 if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1241 && let hir::LifetimeKind::Param(param_id) = lifetime_ref.kind
1242 && let Some(generics) =
1243 self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
1244 && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1245 && param.is_elided_lifetime()
1246 && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
1247 && !self.tcx.features().anonymous_lifetime_in_impl_trait()
1248 {
1249 let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
1250 &self.tcx.sess,
1251 sym::anonymous_lifetime_in_impl_trait,
1252 lifetime_ref.ident.span,
1253 "anonymous lifetimes in `impl Trait` are unstable",
1254 );
1255
1256 if let Some(generics) =
1257 self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
1258 {
1259 let new_param_sugg =
1260 if let Some(span) = generics.span_for_lifetime_suggestion() {
1261 (span, "'a, ".to_owned())
1262 } else {
1263 (generics.span, "<'a>".to_owned())
1264 };
1265
1266 let lifetime_sugg = lifetime_ref.suggestion("'a");
1267 let suggestions = vec![lifetime_sugg, new_param_sugg];
1268
1269 diag.span_label(
1270 lifetime_ref.ident.span,
1271 "expected named lifetime parameter",
1272 );
1273 diag.multipart_suggestion(
1274 "consider introducing a named lifetime parameter",
1275 suggestions,
1276 rustc_errors::Applicability::MaybeIncorrect,
1277 );
1278 }
1279
1280 diag.emit();
1281 return;
1282 }
1283 scope = s;
1284 }
1285
1286 Scope::Opaque { captures, def_id, s } => {
1287 opaque_capture_scopes.push((def_id, captures));
1288 late_depth = 0;
1289 scope = s;
1290 }
1291
1292 Scope::ObjectLifetimeDefault { s, .. }
1293 | Scope::Supertrait { s, .. }
1294 | Scope::TraitRefBoundary { s, .. } => {
1295 scope = s;
1296 }
1297
1298 Scope::LateBoundary { s, what, deny_late_regions } => {
1299 if deny_late_regions {
1300 crossed_late_boundary = Some(what);
1301 }
1302 scope = s;
1303 }
1304 }
1305 };
1306
1307 if let Some(mut def) = result {
1308 def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
1309
1310 if let ResolvedArg::EarlyBound(..) = def {
1311 } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
1313 && let Some(what) = crossed_late_boundary
1314 {
1315 let use_span = lifetime_ref.ident.span;
1316 let def_span = self.tcx.def_span(param_def_id);
1317 let guar = match self.tcx.def_kind(param_def_id) {
1318 DefKind::LifetimeParam => {
1319 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Lifetime {
1320 use_span,
1321 def_span,
1322 what,
1323 })
1324 }
1325 kind => span_bug!(
1326 use_span,
1327 "did not expect to resolve lifetime to {}",
1328 kind.descr(param_def_id.to_def_id())
1329 ),
1330 };
1331 def = ResolvedArg::Error(guar);
1332 } else if let Some(body_id) = outermost_body {
1333 let fn_id = self.tcx.hir_body_owner(body_id);
1334 match self.tcx.hir_node(fn_id) {
1335 Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
1336 | Node::TraitItem(hir::TraitItem {
1337 owner_id,
1338 kind: hir::TraitItemKind::Fn(..),
1339 ..
1340 })
1341 | Node::ImplItem(hir::ImplItem {
1342 owner_id,
1343 kind: hir::ImplItemKind::Fn(..),
1344 ..
1345 }) => {
1346 def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
1347 }
1348 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1349 def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
1350 }
1351 _ => {}
1352 }
1353 }
1354
1355 self.insert_lifetime(lifetime_ref, def);
1356 return;
1357 }
1358
1359 let mut scope = self.scope;
1369 loop {
1370 match *scope {
1371 Scope::Binder {
1372 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1373 } => {
1374 self.tcx.dcx().emit_err(errors::LateBoundInApit::Lifetime {
1375 span: lifetime_ref.ident.span,
1376 param_span: self.tcx.def_span(region_def_id),
1377 });
1378 return;
1379 }
1380 Scope::Root { .. } => break,
1381 Scope::Binder { s, .. }
1382 | Scope::Body { s, .. }
1383 | Scope::Opaque { s, .. }
1384 | Scope::ObjectLifetimeDefault { s, .. }
1385 | Scope::Supertrait { s, .. }
1386 | Scope::TraitRefBoundary { s, .. }
1387 | Scope::LateBoundary { s, .. } => {
1388 scope = s;
1389 }
1390 }
1391 }
1392
1393 self.tcx.dcx().span_delayed_bug(
1394 lifetime_ref.ident.span,
1395 format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1396 );
1397 }
1398
1399 fn check_lifetime_is_capturable(
1404 &self,
1405 opaque_def_id: LocalDefId,
1406 lifetime: ResolvedArg,
1407 capture_span: Span,
1408 ) -> Result<(), ErrorGuaranteed> {
1409 let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
1410 let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
1411 let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
1412 hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
1415 hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
1417 hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(_), .. }) => {
1418 "higher-ranked lifetime from function pointer"
1419 }
1420 hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
1421 "higher-ranked lifetime from `dyn` type"
1422 }
1423 _ => "higher-ranked lifetime",
1424 };
1425
1426 let decl_span = self.tcx.def_span(lifetime_def_id);
1427 let (span, label) = if capture_span != decl_span {
1428 (capture_span, None)
1429 } else {
1430 let opaque_span = self.tcx.def_span(opaque_def_id);
1431 (opaque_span, Some(opaque_span))
1432 };
1433
1434 let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
1436 span,
1437 label,
1438 decl_span,
1439 bad_place,
1440 });
1441 Err(guar)
1442 }
1443
1444 #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
1445 fn remap_opaque_captures(
1446 &mut self,
1447 opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
1448 mut lifetime: ResolvedArg,
1449 ident: Ident,
1450 ) -> ResolvedArg {
1451 if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
1452 if let Err(guar) =
1453 self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
1454 {
1455 lifetime = ResolvedArg::Error(guar);
1456 }
1457 }
1458
1459 for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
1460 let mut captures = captures.borrow_mut();
1461 let remapped = *captures.entry(lifetime).or_insert_with(|| {
1462 let feed = self.tcx.create_def(
1467 opaque_def_id,
1468 None,
1469 DefKind::LifetimeParam,
1470 Some(DefPathData::OpaqueLifetime(ident.name)),
1471 &mut self.disambiguator,
1472 );
1473 feed.def_span(ident.span);
1474 feed.def_ident_span(Some(ident.span));
1475 feed.def_id()
1476 });
1477 lifetime = ResolvedArg::EarlyBound(remapped);
1478 }
1479 lifetime
1480 }
1481
1482 fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
1483 let mut late_depth = 0;
1488 let mut scope = self.scope;
1489 let mut crossed_late_boundary = None;
1490
1491 let result = loop {
1492 match *scope {
1493 Scope::Body { s, .. } => {
1494 scope = s;
1495 }
1496
1497 Scope::Root { opt_parent_item } => {
1498 if let Some(parent_item) = opt_parent_item
1499 && let parent_generics = self.tcx.generics_of(parent_item)
1500 && parent_generics
1501 .param_def_id_to_index(self.tcx, param_def_id.to_def_id())
1502 .is_some()
1503 {
1504 break Some(ResolvedArg::EarlyBound(param_def_id));
1505 }
1506 break None;
1507 }
1508
1509 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
1510 if let Some(&def) = bound_vars.get(¶m_def_id) {
1511 break Some(def.shifted(late_depth));
1512 }
1513 match scope_type {
1514 BinderScopeType::Normal => late_depth += 1,
1515 BinderScopeType::Concatenating => {}
1516 }
1517 scope = s;
1518 }
1519
1520 Scope::ObjectLifetimeDefault { s, .. }
1521 | Scope::Opaque { s, .. }
1522 | Scope::Supertrait { s, .. }
1523 | Scope::TraitRefBoundary { s, .. } => {
1524 scope = s;
1525 }
1526
1527 Scope::LateBoundary { s, what, deny_late_regions: _ } => {
1528 crossed_late_boundary = Some(what);
1529 scope = s;
1530 }
1531 }
1532 };
1533
1534 if let Some(def) = result {
1535 if let ResolvedArg::LateBound(..) = def
1536 && let Some(what) = crossed_late_boundary
1537 {
1538 let use_span = self.tcx.hir_span(hir_id);
1539 let def_span = self.tcx.def_span(param_def_id);
1540 let guar = match self.tcx.def_kind(param_def_id) {
1541 DefKind::ConstParam => {
1542 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Const {
1543 use_span,
1544 def_span,
1545 what,
1546 })
1547 }
1548 DefKind::TyParam => {
1549 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Type {
1550 use_span,
1551 def_span,
1552 what,
1553 })
1554 }
1555 kind => span_bug!(
1556 use_span,
1557 "did not expect to resolve non-lifetime param to {}",
1558 kind.descr(param_def_id.to_def_id())
1559 ),
1560 };
1561 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1562 } else {
1563 self.rbv.defs.insert(hir_id.local_id, def);
1564 }
1565 return;
1566 }
1567
1568 let mut scope = self.scope;
1578 loop {
1579 match *scope {
1580 Scope::Binder {
1581 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1582 } => {
1583 let guar = self.tcx.dcx().emit_err(match self.tcx.def_kind(param_def_id) {
1584 DefKind::TyParam => errors::LateBoundInApit::Type {
1585 span: self.tcx.hir_span(hir_id),
1586 param_span: self.tcx.def_span(param_def_id),
1587 },
1588 DefKind::ConstParam => errors::LateBoundInApit::Const {
1589 span: self.tcx.hir_span(hir_id),
1590 param_span: self.tcx.def_span(param_def_id),
1591 },
1592 kind => {
1593 bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1594 }
1595 });
1596 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1597 return;
1598 }
1599 Scope::Root { .. } => break,
1600 Scope::Binder { s, .. }
1601 | Scope::Body { s, .. }
1602 | Scope::Opaque { s, .. }
1603 | Scope::ObjectLifetimeDefault { s, .. }
1604 | Scope::Supertrait { s, .. }
1605 | Scope::TraitRefBoundary { s, .. }
1606 | Scope::LateBoundary { s, .. } => {
1607 scope = s;
1608 }
1609 }
1610 }
1611
1612 self.tcx
1613 .dcx()
1614 .span_bug(self.tcx.hir_span(hir_id), format!("could not resolve {param_def_id:?}"));
1615 }
1616
1617 #[instrument(level = "debug", skip(self))]
1618 fn visit_segment_args(
1619 &mut self,
1620 res: Res,
1621 depth: usize,
1622 generic_args: &'tcx hir::GenericArgs<'tcx>,
1623 ) {
1624 if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
1625 self.visit_fn_like_elision(inputs, Some(output), false);
1626 return;
1627 }
1628
1629 for arg in generic_args.args {
1630 if let hir::GenericArg::Lifetime(lt) = arg {
1631 self.visit_lifetime(lt);
1632 }
1633 }
1634
1635 let type_def_id = match res {
1638 Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1639 Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1640 Res::Def(
1641 DefKind::Struct
1642 | DefKind::Union
1643 | DefKind::Enum
1644 | DefKind::TyAlias
1645 | DefKind::Trait,
1646 def_id,
1647 ) if depth == 0 => Some(def_id),
1648 _ => None,
1649 };
1650
1651 debug!(?type_def_id);
1652
1653 let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1669 let in_body = {
1670 let mut scope = self.scope;
1671 loop {
1672 match *scope {
1673 Scope::Root { .. } => break false,
1674
1675 Scope::Body { .. } => break true,
1676
1677 Scope::Binder { s, .. }
1678 | Scope::ObjectLifetimeDefault { s, .. }
1679 | Scope::Opaque { s, .. }
1680 | Scope::Supertrait { s, .. }
1681 | Scope::TraitRefBoundary { s, .. }
1682 | Scope::LateBoundary { s, .. } => {
1683 scope = s;
1684 }
1685 }
1686 }
1687 };
1688
1689 let rbv = &self.rbv;
1690 let generics = self.tcx.generics_of(def_id);
1691
1692 debug_assert_eq!(generics.parent_count, 0);
1694
1695 let set_to_region = |set: ObjectLifetimeDefault| match set {
1696 ObjectLifetimeDefault::Empty => {
1697 if in_body {
1698 None
1699 } else {
1700 Some(ResolvedArg::StaticLifetime)
1701 }
1702 }
1703 ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
1704 ObjectLifetimeDefault::Param(param_def_id) => {
1705 let index = generics.param_def_id_to_index[¶m_def_id] as usize;
1707 generic_args.args.get(index).and_then(|arg| match arg {
1708 GenericArg::Lifetime(lt) => rbv.defs.get(<.hir_id.local_id).copied(),
1709 _ => None,
1710 })
1711 }
1712 ObjectLifetimeDefault::Ambiguous => None,
1713 };
1714 generics
1715 .own_params
1716 .iter()
1717 .filter_map(|param| {
1718 match self.tcx.def_kind(param.def_id) {
1719 DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1724 DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1725 DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1728 dk => bug!("unexpected def_kind {:?}", dk),
1729 }
1730 })
1731 .map(set_to_region)
1732 .collect()
1733 });
1734
1735 debug!(?object_lifetime_defaults);
1736
1737 let mut i = 0;
1738 for arg in generic_args.args {
1739 match arg {
1740 GenericArg::Lifetime(_) => {}
1741 GenericArg::Type(ty) => {
1742 if let Some(<) = object_lifetime_defaults.get(i) {
1743 let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1744 self.with(scope, |this| this.visit_ty(ty));
1745 } else {
1746 self.visit_ty(ty);
1747 }
1748 i += 1;
1749 }
1750 GenericArg::Const(ct) => {
1751 self.visit_const_arg(ct);
1752 i += 1;
1753 }
1754 GenericArg::Infer(inf) => {
1755 self.visit_id(inf.hir_id);
1756 i += 1;
1757 }
1758 }
1759 }
1760
1761 let has_lifetime_parameter =
1786 generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1787
1788 for constraint in generic_args.constraints {
1791 let scope = Scope::ObjectLifetimeDefault {
1792 lifetime: if has_lifetime_parameter {
1793 None
1794 } else {
1795 Some(ResolvedArg::StaticLifetime)
1796 },
1797 s: self.scope,
1798 };
1799 if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
1813 {
1814 let bound_vars = if let Some(type_def_id) = type_def_id
1815 && self.tcx.def_kind(type_def_id) == DefKind::Trait
1816 && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
1817 self.tcx,
1818 type_def_id,
1819 constraint.ident,
1820 ty::AssocTag::Fn,
1821 ) {
1822 bound_vars.extend(
1823 self.tcx
1824 .generics_of(assoc_fn.def_id)
1825 .own_params
1826 .iter()
1827 .map(|param| generic_param_def_as_bound_arg(param)),
1828 );
1829 bound_vars.extend(
1830 self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars(),
1831 );
1832 bound_vars
1833 } else {
1834 self.tcx
1835 .dcx()
1836 .span_delayed_bug(constraint.ident.span, "bad return type notation here");
1837 vec![]
1838 };
1839 self.with(scope, |this| {
1840 let scope = Scope::Supertrait { bound_vars, s: this.scope };
1841 this.with(scope, |this| {
1842 let (bound_vars, _) = this.poly_trait_ref_binder_info();
1843 this.record_late_bound_vars(constraint.hir_id, bound_vars);
1844 this.visit_assoc_item_constraint(constraint)
1845 });
1846 });
1847 } else if let Some(type_def_id) = type_def_id {
1848 let bound_vars = BoundVarContext::supertrait_hrtb_vars(
1849 self.tcx,
1850 type_def_id,
1851 constraint.ident,
1852 ty::AssocTag::Type,
1853 )
1854 .map(|(bound_vars, _)| bound_vars);
1855 self.with(scope, |this| {
1856 let scope = Scope::Supertrait {
1857 bound_vars: bound_vars.unwrap_or_default(),
1858 s: this.scope,
1859 };
1860 this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1861 });
1862 } else {
1863 self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1864 }
1865 }
1866 }
1867
1868 fn supertrait_hrtb_vars(
1881 tcx: TyCtxt<'tcx>,
1882 def_id: DefId,
1883 assoc_ident: Ident,
1884 assoc_tag: ty::AssocTag,
1885 ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
1886 let trait_defines_associated_item_named = |trait_def_id: DefId| {
1887 tcx.associated_items(trait_def_id).find_by_ident_and_kind(
1888 tcx,
1889 assoc_ident,
1890 assoc_tag,
1891 trait_def_id,
1892 )
1893 };
1894
1895 use smallvec::{SmallVec, smallvec};
1896 let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1897 smallvec![(def_id, smallvec![])];
1898 let mut visited: FxHashSet<DefId> = FxHashSet::default();
1899 loop {
1900 let Some((def_id, bound_vars)) = stack.pop() else {
1901 break None;
1902 };
1903 match tcx.def_kind(def_id) {
1906 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
1907 _ => break None,
1908 }
1909
1910 if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
1911 break Some((bound_vars.into_iter().collect(), assoc_item));
1912 }
1913 let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_ident));
1914 let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| {
1915 let bound_predicate = pred.kind();
1916 match bound_predicate.skip_binder() {
1917 ty::ClauseKind::Trait(data) => {
1918 let pred_bound_vars = bound_predicate.bound_vars();
1921 let mut all_bound_vars = bound_vars.clone();
1922 all_bound_vars.extend(pred_bound_vars.iter());
1923 let super_def_id = data.trait_ref.def_id;
1924 Some((super_def_id, all_bound_vars))
1925 }
1926 _ => None,
1927 }
1928 });
1929
1930 let obligations = obligations.filter(|o| visited.insert(o.0));
1931 stack.extend(obligations);
1932 }
1933 }
1934
1935 #[instrument(level = "debug", skip(self))]
1936 fn visit_fn_like_elision(
1937 &mut self,
1938 inputs: &'tcx [hir::Ty<'tcx>],
1939 output: Option<&'tcx hir::Ty<'tcx>>,
1940 in_closure: bool,
1941 ) {
1942 self.with(
1943 Scope::ObjectLifetimeDefault {
1944 lifetime: Some(ResolvedArg::StaticLifetime),
1945 s: self.scope,
1946 },
1947 |this| {
1948 for input in inputs {
1949 this.visit_ty_unambig(input);
1950 }
1951 if !in_closure && let Some(output) = output {
1952 this.visit_ty_unambig(output);
1953 }
1954 },
1955 );
1956 if in_closure && let Some(output) = output {
1957 self.visit_ty_unambig(output);
1958 }
1959 }
1960
1961 #[instrument(level = "debug", skip(self))]
1962 fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
1963 let mut late_depth = 0;
1964 let mut scope = self.scope;
1965 let mut opaque_capture_scopes = vec![];
1966 let mut lifetime = loop {
1967 match *scope {
1968 Scope::Binder { s, scope_type, .. } => {
1969 match scope_type {
1970 BinderScopeType::Normal => late_depth += 1,
1971 BinderScopeType::Concatenating => {}
1972 }
1973 scope = s;
1974 }
1975
1976 Scope::Root { .. } => break ResolvedArg::StaticLifetime,
1977
1978 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
1979
1980 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
1981 break l.shifted(late_depth);
1982 }
1983
1984 Scope::Opaque { captures, def_id, s } => {
1985 opaque_capture_scopes.push((def_id, captures));
1986 late_depth = 0;
1987 scope = s;
1988 }
1989
1990 Scope::Supertrait { s, .. }
1991 | Scope::TraitRefBoundary { s, .. }
1992 | Scope::LateBoundary { s, .. } => {
1993 scope = s;
1994 }
1995 }
1996 };
1997
1998 lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
1999
2000 self.insert_lifetime(lifetime_ref, lifetime);
2001 }
2002
2003 #[instrument(level = "debug", skip(self))]
2004 fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
2005 debug!(span = ?lifetime_ref.ident.span);
2006 self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
2007 }
2008
2009 fn try_append_return_type_notation_params(
2028 &mut self,
2029 hir_id: HirId,
2030 hir_ty: &'tcx hir::Ty<'tcx>,
2031 ) {
2032 let hir::TyKind::Path(qpath) = hir_ty.kind else {
2033 return;
2037 };
2038
2039 let (mut bound_vars, item_def_id, item_segment) = match qpath {
2040 hir::QPath::Resolved(_, path)
2042 if let [.., item_segment] = &path.segments[..]
2043 && item_segment.args.is_some_and(|args| {
2044 matches!(
2045 args.parenthesized,
2046 hir::GenericArgsParentheses::ReturnTypeNotation
2047 )
2048 }) =>
2049 {
2050 match path.res {
2051 Res::Err => return,
2052 Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
2053 _ => bug!("only expected method resolution for fully qualified RTN"),
2054 }
2055 }
2056
2057 hir::QPath::TypeRelative(qself, item_segment)
2059 if item_segment.args.is_some_and(|args| {
2060 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2061 }) =>
2062 {
2063 let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
2066 return;
2067 };
2068 match path.res {
2069 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
2070 let mut bounds =
2071 self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
2072 BoundVarContext::supertrait_hrtb_vars(
2073 self.tcx,
2074 trait_def_id,
2075 item_segment.ident,
2076 ty::AssocTag::Fn,
2077 )
2078 });
2079
2080 let Some((bound_vars, assoc_item)) = bounds.next() else {
2081 self.tcx
2083 .dcx()
2084 .span_delayed_bug(path.span, "no resolution for RTN path");
2085 return;
2086 };
2087
2088 for (second_vars, second_assoc_item) in bounds {
2091 if second_vars != bound_vars || second_assoc_item != assoc_item {
2092 self.tcx.dcx().span_delayed_bug(
2094 path.span,
2095 "ambiguous resolution for RTN path",
2096 );
2097 return;
2098 }
2099 }
2100
2101 (bound_vars, assoc_item.def_id, item_segment)
2102 }
2103 Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
2106 let hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = self
2107 .tcx
2108 .hir_node_by_def_id(impl_def_id.expect_local())
2109 .expect_item()
2110 .kind
2111 else {
2112 return;
2113 };
2114 let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
2115 return;
2116 };
2117 let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
2118 self.tcx,
2119 trait_def_id,
2120 item_segment.ident,
2121 ty::AssocTag::Fn,
2122 ) else {
2123 return;
2124 };
2125 (bound_vars, assoc_item.def_id, item_segment)
2126 }
2127 _ => return,
2128 }
2129 }
2130
2131 _ => return,
2132 };
2133
2134 bound_vars.extend(
2138 self.tcx
2139 .generics_of(item_def_id)
2140 .own_params
2141 .iter()
2142 .map(|param| generic_param_def_as_bound_arg(param)),
2143 );
2144 bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
2145
2146 let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
2162 let existing_bound_vars_saved = existing_bound_vars.clone();
2163 existing_bound_vars.extend(bound_vars);
2164 self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
2165 }
2166
2167 fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
2170 gen move {
2171 let mut scope = self.scope;
2172 loop {
2173 let hir_id = match *scope {
2174 Scope::Binder { hir_id, .. } => Some(hir_id),
2175 Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2176 Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2177 }
2178 Scope::Body { .. }
2179 | Scope::ObjectLifetimeDefault { .. }
2180 | Scope::Supertrait { .. }
2181 | Scope::TraitRefBoundary { .. }
2182 | Scope::LateBoundary { .. }
2183 | Scope::Opaque { .. }
2184 | Scope::Root { opt_parent_item: None } => None,
2185 };
2186
2187 if let Some(hir_id) = hir_id {
2188 let node = self.tcx.hir_node(hir_id);
2189 if let Res::SelfTyParam { trait_: _ } = expected_res
2193 && let hir::Node::Item(item) = node
2194 && let hir::ItemKind::Trait(..) = item.kind
2195 {
2196 yield item.owner_id.def_id.to_def_id();
2199 } else if let Some(generics) = node.generics() {
2200 for pred in generics.predicates {
2201 let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
2202 continue;
2203 };
2204 let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2205 pred.bounded_ty.kind
2206 else {
2207 continue;
2208 };
2209 if bounded_path.res != expected_res {
2211 continue;
2212 }
2213 for pred in pred.bounds {
2214 match pred {
2215 hir::GenericBound::Trait(poly_trait_ref) => {
2216 if let Some(def_id) =
2217 poly_trait_ref.trait_ref.trait_def_id()
2218 {
2219 yield def_id;
2220 }
2221 }
2222 hir::GenericBound::Outlives(_)
2223 | hir::GenericBound::Use(_, _) => {}
2224 }
2225 }
2226 }
2227 }
2228 }
2229
2230 match *scope {
2231 Scope::Binder { s, .. }
2232 | Scope::Body { s, .. }
2233 | Scope::ObjectLifetimeDefault { s, .. }
2234 | Scope::Supertrait { s, .. }
2235 | Scope::TraitRefBoundary { s }
2236 | Scope::LateBoundary { s, .. }
2237 | Scope::Opaque { s, .. } => {
2238 scope = s;
2239 }
2240 Scope::Root { .. } => break,
2241 }
2242 }
2243 }
2244 }
2245}
2246
2247fn is_late_bound_map(
2258 tcx: TyCtxt<'_>,
2259 owner_id: hir::OwnerId,
2260) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2261 let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?;
2262 let generics = tcx.hir_get_generics(owner_id.def_id)?;
2263
2264 let mut late_bound = FxIndexSet::default();
2265
2266 let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2267 for arg_ty in sig.decl.inputs {
2268 constrained_by_input.visit_ty_unambig(arg_ty);
2269 }
2270
2271 let mut appears_in_output =
2272 AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
2273 intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2274 if appears_in_output.has_fully_capturing_opaque {
2275 appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2276 }
2277
2278 debug!(?constrained_by_input.regions);
2279
2280 let mut appears_in_where_clause =
2285 AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
2286 appears_in_where_clause.visit_generics(generics);
2287 debug!(?appears_in_where_clause.regions);
2288
2289 for param in generics.params {
2294 match param.kind {
2295 hir::GenericParamKind::Lifetime { .. } => { }
2296
2297 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2299 }
2300
2301 if appears_in_where_clause.regions.contains(¶m.def_id) {
2303 continue;
2304 }
2305
2306 if !constrained_by_input.regions.contains(¶m.def_id)
2308 && appears_in_output.regions.contains(¶m.def_id)
2309 {
2310 continue;
2311 }
2312
2313 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2314
2315 let inserted = late_bound.insert(param.hir_id.local_id);
2316 assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2317 }
2318
2319 debug!(?late_bound);
2320 return Some(tcx.arena.alloc(late_bound));
2321
2322 struct ConstrainedCollectorPostHirTyLowering {
2344 arg_is_constrained: Box<[bool]>,
2345 }
2346
2347 use ty::Ty;
2348 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2349 fn visit_ty(&mut self, t: Ty<'tcx>) {
2350 match t.kind() {
2351 ty::Param(param_ty) => {
2352 self.arg_is_constrained[param_ty.index as usize] = true;
2353 }
2354 ty::Alias(ty::Projection | ty::Inherent, _) => return,
2355 _ => (),
2356 }
2357 t.super_visit_with(self)
2358 }
2359
2360 fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2361
2362 fn visit_region(&mut self, r: ty::Region<'tcx>) {
2363 debug!("r={:?}", r.kind());
2364 if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2365 self.arg_is_constrained[region.index as usize] = true;
2366 }
2367 }
2368 }
2369
2370 struct ConstrainedCollector<'tcx> {
2371 tcx: TyCtxt<'tcx>,
2372 regions: FxHashSet<LocalDefId>,
2373 }
2374
2375 impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2376 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2377 match ty.kind {
2378 hir::TyKind::Path(
2379 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2380 ) => {
2381 }
2385
2386 hir::TyKind::Path(hir::QPath::Resolved(
2387 None,
2388 hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2389 )) => {
2390 let generics = self.tcx.generics_of(alias_def);
2393 let mut walker = ConstrainedCollectorPostHirTyLowering {
2394 arg_is_constrained: vec![false; generics.own_params.len()]
2395 .into_boxed_slice(),
2396 };
2397 walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2398
2399 match segments.last() {
2400 Some(hir::PathSegment { args: Some(args), .. }) => {
2401 let tcx = self.tcx;
2402 for constrained_arg in
2403 args.args.iter().enumerate().flat_map(|(n, arg)| {
2404 match walker.arg_is_constrained.get(n) {
2405 Some(true) => Some(arg),
2406 Some(false) => None,
2407 None => {
2408 tcx.dcx().span_delayed_bug(
2409 *span,
2410 format!(
2411 "Incorrect generic arg count for alias {alias_def:?}"
2412 ),
2413 );
2414 None
2415 }
2416 }
2417 })
2418 {
2419 self.visit_generic_arg(constrained_arg);
2420 }
2421 }
2422 Some(_) => (),
2423 None => bug!("Path with no segments or self type"),
2424 }
2425 }
2426
2427 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2428 if let Some(last_segment) = path.segments.last() {
2434 self.visit_path_segment(last_segment);
2435 }
2436 }
2437
2438 _ => {
2439 intravisit::walk_ty(self, ty);
2440 }
2441 }
2442 }
2443
2444 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2445 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2446 self.regions.insert(def_id);
2447 }
2448 }
2449 }
2450
2451 struct AllCollector {
2452 has_fully_capturing_opaque: bool,
2453 regions: FxHashSet<LocalDefId>,
2454 }
2455
2456 impl<'tcx> Visitor<'tcx> for AllCollector {
2457 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2458 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2459 self.regions.insert(def_id);
2460 }
2461 }
2462
2463 fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
2464 if !self.has_fully_capturing_opaque {
2465 self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
2466 }
2467 intravisit::walk_opaque_ty(self, opaque);
2468 }
2469 }
2470}
2471
2472fn deny_non_region_late_bound(
2473 tcx: TyCtxt<'_>,
2474 bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2475 where_: &str,
2476) {
2477 let mut first = true;
2478
2479 for (var, arg) in bound_vars {
2480 let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2481 span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2482 };
2483
2484 let what = match param.kind {
2485 hir::GenericParamKind::Type { .. } => "type",
2486 hir::GenericParamKind::Const { .. } => "const",
2487 hir::GenericParamKind::Lifetime { .. } => continue,
2488 };
2489
2490 let diag = tcx.dcx().struct_span_err(
2491 param.span,
2492 format!("late-bound {what} parameter not allowed on {where_}"),
2493 );
2494
2495 let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first);
2496
2497 first = false;
2498 *arg = ResolvedArg::Error(guar);
2499 }
2500}