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