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::intravisit::{self, InferKind, Visitor, VisitorExt};
18use rustc_hir::{
19 self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
20};
21use rustc_macros::extension;
22use rustc_middle::hir::nested_filter;
23use rustc_middle::middle::resolve_bound_vars::*;
24use rustc_middle::query::Providers;
25use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
26use rustc_middle::{bug, span_bug};
27use rustc_span::def_id::{DefId, LocalDefId};
28use rustc_span::{Ident, Span, sym};
29use tracing::{debug, debug_span, instrument};
30
31use crate::errors;
32
33#[extension(trait RegionExt)]
34impl ResolvedArg {
35 fn early(param: &GenericParam<'_>) -> ResolvedArg {
36 ResolvedArg::EarlyBound(param.def_id)
37 }
38
39 fn late(idx: u32, param: &GenericParam<'_>) -> ResolvedArg {
40 ResolvedArg::LateBound(ty::INNERMOST, idx, param.def_id)
41 }
42
43 fn id(&self) -> Option<LocalDefId> {
44 match *self {
45 ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
46
47 ResolvedArg::EarlyBound(id)
48 | ResolvedArg::LateBound(_, _, id)
49 | ResolvedArg::Free(_, id) => Some(id),
50 }
51 }
52
53 fn shifted(self, amount: u32) -> ResolvedArg {
54 match self {
55 ResolvedArg::LateBound(debruijn, idx, id) => {
56 ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
57 }
58 _ => self,
59 }
60 }
61}
62
63struct BoundVarContext<'a, 'tcx> {
64 tcx: TyCtxt<'tcx>,
65 rbv: &'a mut ResolveBoundVars,
66 scope: ScopeRef<'a>,
67}
68
69#[derive(Debug)]
70enum Scope<'a> {
71 Binder {
76 bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
79
80 scope_type: BinderScopeType,
81
82 hir_id: HirId,
87
88 s: ScopeRef<'a>,
89
90 where_bound_origin: Option<hir::PredicateOrigin>,
96 },
97
98 Body {
103 id: hir::BodyId,
104 s: ScopeRef<'a>,
105 },
106
107 ObjectLifetimeDefault {
111 lifetime: Option<ResolvedArg>,
112 s: ScopeRef<'a>,
113 },
114
115 Supertrait {
120 bound_vars: Vec<ty::BoundVariableKind>,
121 s: ScopeRef<'a>,
122 },
123
124 TraitRefBoundary {
125 s: ScopeRef<'a>,
126 },
127
128 Opaque {
137 def_id: LocalDefId,
139 captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
141
142 s: ScopeRef<'a>,
143 },
144
145 LateBoundary {
151 s: ScopeRef<'a>,
152 what: &'static str,
153 deny_late_regions: bool,
154 },
155
156 Root {
157 opt_parent_item: Option<LocalDefId>,
158 },
159}
160
161impl<'a> Scope<'a> {
162 fn debug_truncated(&'a self) -> impl fmt::Debug + 'a {
164 fmt::from_fn(move |f| match self {
165 Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
166 .debug_struct("Binder")
167 .field("bound_vars", bound_vars)
168 .field("scope_type", scope_type)
169 .field("hir_id", hir_id)
170 .field("where_bound_origin", where_bound_origin)
171 .field("s", &"..")
172 .finish(),
173 Self::Opaque { captures, def_id, s: _ } => f
174 .debug_struct("Opaque")
175 .field("def_id", def_id)
176 .field("captures", &captures.borrow())
177 .field("s", &"..")
178 .finish(),
179 Self::Body { id, s: _ } => {
180 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
181 }
182 Self::ObjectLifetimeDefault { lifetime, s: _ } => f
183 .debug_struct("ObjectLifetimeDefault")
184 .field("lifetime", lifetime)
185 .field("s", &"..")
186 .finish(),
187 Self::Supertrait { bound_vars, s: _ } => f
188 .debug_struct("Supertrait")
189 .field("bound_vars", bound_vars)
190 .field("s", &"..")
191 .finish(),
192 Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
193 Self::LateBoundary { s: _, what, deny_late_regions } => f
194 .debug_struct("LateBoundary")
195 .field("what", what)
196 .field("deny_late_regions", deny_late_regions)
197 .finish(),
198 Self::Root { opt_parent_item } => {
199 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
200 }
201 })
202 }
203}
204
205#[derive(Copy, Clone, Debug)]
206enum BinderScopeType {
207 Normal,
209 Concatenating,
219}
220
221type ScopeRef<'a> = &'a Scope<'a>;
222
223pub(crate) fn provide(providers: &mut Providers) {
224 *providers = Providers {
225 resolve_bound_vars,
226
227 named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
228 is_late_bound_map,
229 object_lifetime_default,
230 late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
231 opaque_captured_lifetimes: |tcx, id| {
232 &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
233 .opaque_captured_lifetimes
234 .get(&id)
235 .map_or(&[][..], |x| &x[..])
236 },
237
238 ..*providers
239 };
240}
241
242#[instrument(level = "debug", skip(tcx))]
246fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
247 let mut rbv = ResolveBoundVars::default();
248 let mut visitor =
249 BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
250 match tcx.hir_owner_node(local_def_id) {
251 hir::OwnerNode::Item(item) => visitor.visit_item(item),
252 hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
253 hir::OwnerNode::TraitItem(item) => {
254 let scope =
255 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
256 visitor.scope = &scope;
257 visitor.visit_trait_item(item)
258 }
259 hir::OwnerNode::ImplItem(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_impl_item(item)
264 }
265 hir::OwnerNode::Crate(_) => {}
266 hir::OwnerNode::Synthetic => unreachable!(),
267 }
268
269 debug!(?rbv.defs);
270 debug!(?rbv.late_bound_vars);
271 debug!(?rbv.opaque_captured_lifetimes);
272 rbv
273}
274
275fn late_arg_as_bound_arg<'tcx>(
276 tcx: TyCtxt<'tcx>,
277 param: &GenericParam<'tcx>,
278) -> ty::BoundVariableKind {
279 let def_id = param.def_id.to_def_id();
280 let name = tcx.item_name(def_id);
281 match param.kind {
282 GenericParamKind::Lifetime { .. } => {
283 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
284 }
285 GenericParamKind::Type { .. } => {
286 ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name))
287 }
288 GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
289 }
290}
291
292fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
296 match param.kind {
297 ty::GenericParamDefKind::Lifetime => {
298 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id, param.name))
299 }
300 ty::GenericParamDefKind::Type { .. } => {
301 ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
302 }
303 ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
304 }
305}
306
307fn opaque_captures_all_in_scope_lifetimes<'tcx>(
312 tcx: TyCtxt<'tcx>,
313 opaque: &'tcx hir::OpaqueTy<'tcx>,
314) -> bool {
315 match opaque.origin {
316 _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
319 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
320 _ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
321 true
322 }
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 =
523 opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
524 if capture_all_in_scope_lifetimes {
525 let lifetime_ident = |def_id: LocalDefId| {
526 let name = self.tcx.item_name(def_id.to_def_id());
527 let span = self.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.res {
657 LifetimeName::Param(def_id) => {
658 self.resolve_lifetime_ref(def_id, lt);
659 }
660 LifetimeName::Error => {}
661 LifetimeName::ImplicitObjectLifetimeDefault
662 | LifetimeName::Infer
663 | LifetimeName::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.res {
785 LifetimeName::ImplicitObjectLifetimeDefault => {
786 self.resolve_object_lifetime_default(&*lifetime)
791 }
792 LifetimeName::Infer => {
793 }
799 LifetimeName::Param(..) | LifetimeName::Static => {
800 self.visit_lifetime(&*lifetime);
802 }
803 LifetimeName::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.res {
884 hir::LifetimeName::Static => {
885 self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
886 }
887 hir::LifetimeName::Param(param_def_id) => {
888 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
889 }
890 hir::LifetimeName::Error => {}
892 hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::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.res);
1074 }
1075 }
1076 }
1077
1078 match set {
1079 Set1::Empty => ObjectLifetimeDefault::Empty,
1080 Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
1081 Set1::One(hir::LifetimeName::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, .. } = self;
1102 let mut this = BoundVarContext { tcx: *tcx, rbv, 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::LifetimeName::Param(param_id) = lifetime_ref.res
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 &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(opaque_def_id, ident.name, DefKind::LifetimeParam);
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::AssocKind::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::AssocKind::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_name: Ident,
1884 assoc_kind: ty::AssocKind,
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_name_and_kind(
1888 tcx,
1889 assoc_name,
1890 assoc_kind,
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_name));
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::AssocKind::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(trait_ref), .. }) = 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) = 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::AssocKind::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(
2170 &self,
2171 expected_res: Res,
2172 ) -> impl Iterator<Item = DefId> + use<'tcx, '_> {
2173 std::iter::from_coroutine(
2174 #[coroutine]
2175 move || {
2176 let mut scope = self.scope;
2177 loop {
2178 let hir_id = match *scope {
2179 Scope::Binder { hir_id, .. } => Some(hir_id),
2180 Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2181 Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2182 }
2183 Scope::Body { .. }
2184 | Scope::ObjectLifetimeDefault { .. }
2185 | Scope::Supertrait { .. }
2186 | Scope::TraitRefBoundary { .. }
2187 | Scope::LateBoundary { .. }
2188 | Scope::Opaque { .. }
2189 | Scope::Root { opt_parent_item: None } => None,
2190 };
2191
2192 if let Some(hir_id) = hir_id {
2193 let node = self.tcx.hir_node(hir_id);
2194 if let Res::SelfTyParam { trait_: _ } = expected_res
2198 && let hir::Node::Item(item) = node
2199 && let hir::ItemKind::Trait(..) = item.kind
2200 {
2201 yield item.owner_id.def_id.to_def_id();
2204 } else if let Some(generics) = node.generics() {
2205 for pred in generics.predicates {
2206 let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
2207 else {
2208 continue;
2209 };
2210 let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2211 pred.bounded_ty.kind
2212 else {
2213 continue;
2214 };
2215 if bounded_path.res != expected_res {
2217 continue;
2218 }
2219 for pred in pred.bounds {
2220 match pred {
2221 hir::GenericBound::Trait(poly_trait_ref) => {
2222 if let Some(def_id) =
2223 poly_trait_ref.trait_ref.trait_def_id()
2224 {
2225 yield def_id;
2226 }
2227 }
2228 hir::GenericBound::Outlives(_)
2229 | hir::GenericBound::Use(_, _) => {}
2230 }
2231 }
2232 }
2233 }
2234 }
2235
2236 match *scope {
2237 Scope::Binder { s, .. }
2238 | Scope::Body { s, .. }
2239 | Scope::ObjectLifetimeDefault { s, .. }
2240 | Scope::Supertrait { s, .. }
2241 | Scope::TraitRefBoundary { s }
2242 | Scope::LateBoundary { s, .. }
2243 | Scope::Opaque { s, .. } => {
2244 scope = s;
2245 }
2246 Scope::Root { .. } => break,
2247 }
2248 }
2249 },
2250 )
2251 }
2252}
2253
2254fn is_late_bound_map(
2265 tcx: TyCtxt<'_>,
2266 owner_id: hir::OwnerId,
2267) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2268 let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
2269 let generics = tcx.hir_get_generics(owner_id.def_id)?;
2270
2271 let mut late_bound = FxIndexSet::default();
2272
2273 let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2274 for arg_ty in sig.decl.inputs {
2275 constrained_by_input.visit_ty_unambig(arg_ty);
2276 }
2277
2278 let mut appears_in_output =
2279 AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
2280 intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2281 if appears_in_output.has_fully_capturing_opaque {
2282 appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2283 }
2284
2285 debug!(?constrained_by_input.regions);
2286
2287 let mut appears_in_where_clause =
2292 AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
2293 appears_in_where_clause.visit_generics(generics);
2294 debug!(?appears_in_where_clause.regions);
2295
2296 for param in generics.params {
2301 match param.kind {
2302 hir::GenericParamKind::Lifetime { .. } => { }
2303
2304 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2306 }
2307
2308 if appears_in_where_clause.regions.contains(¶m.def_id) {
2310 continue;
2311 }
2312
2313 if !constrained_by_input.regions.contains(¶m.def_id)
2315 && appears_in_output.regions.contains(¶m.def_id)
2316 {
2317 continue;
2318 }
2319
2320 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2321
2322 let inserted = late_bound.insert(param.hir_id.local_id);
2323 assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2324 }
2325
2326 debug!(?late_bound);
2327 return Some(tcx.arena.alloc(late_bound));
2328
2329 struct ConstrainedCollectorPostHirTyLowering {
2351 arg_is_constrained: Box<[bool]>,
2352 }
2353
2354 use ty::Ty;
2355 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2356 fn visit_ty(&mut self, t: Ty<'tcx>) {
2357 match t.kind() {
2358 ty::Param(param_ty) => {
2359 self.arg_is_constrained[param_ty.index as usize] = true;
2360 }
2361 ty::Alias(ty::Projection | ty::Inherent, _) => return,
2362 _ => (),
2363 }
2364 t.super_visit_with(self)
2365 }
2366
2367 fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2368
2369 fn visit_region(&mut self, r: ty::Region<'tcx>) {
2370 debug!("r={:?}", r.kind());
2371 if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2372 self.arg_is_constrained[region.index as usize] = true;
2373 }
2374 }
2375 }
2376
2377 struct ConstrainedCollector<'tcx> {
2378 tcx: TyCtxt<'tcx>,
2379 regions: FxHashSet<LocalDefId>,
2380 }
2381
2382 impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2383 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2384 match ty.kind {
2385 hir::TyKind::Path(
2386 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2387 ) => {
2388 }
2392
2393 hir::TyKind::Path(hir::QPath::Resolved(
2394 None,
2395 hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2396 )) => {
2397 let generics = self.tcx.generics_of(alias_def);
2400 let mut walker = ConstrainedCollectorPostHirTyLowering {
2401 arg_is_constrained: vec![false; generics.own_params.len()]
2402 .into_boxed_slice(),
2403 };
2404 walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2405
2406 match segments.last() {
2407 Some(hir::PathSegment { args: Some(args), .. }) => {
2408 let tcx = self.tcx;
2409 for constrained_arg in
2410 args.args.iter().enumerate().flat_map(|(n, arg)| {
2411 match walker.arg_is_constrained.get(n) {
2412 Some(true) => Some(arg),
2413 Some(false) => None,
2414 None => {
2415 tcx.dcx().span_delayed_bug(
2416 *span,
2417 format!(
2418 "Incorrect generic arg count for alias {alias_def:?}"
2419 ),
2420 );
2421 None
2422 }
2423 }
2424 })
2425 {
2426 self.visit_generic_arg(constrained_arg);
2427 }
2428 }
2429 Some(_) => (),
2430 None => bug!("Path with no segments or self type"),
2431 }
2432 }
2433
2434 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2435 if let Some(last_segment) = path.segments.last() {
2441 self.visit_path_segment(last_segment);
2442 }
2443 }
2444
2445 _ => {
2446 intravisit::walk_ty(self, ty);
2447 }
2448 }
2449 }
2450
2451 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2452 if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2453 self.regions.insert(def_id);
2454 }
2455 }
2456 }
2457
2458 struct AllCollector<'tcx> {
2459 tcx: TyCtxt<'tcx>,
2460 has_fully_capturing_opaque: bool,
2461 regions: FxHashSet<LocalDefId>,
2462 }
2463
2464 impl<'v> Visitor<'v> for AllCollector<'v> {
2465 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2466 if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
2467 self.regions.insert(def_id);
2468 }
2469 }
2470
2471 fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
2472 if !self.has_fully_capturing_opaque {
2473 self.has_fully_capturing_opaque =
2474 opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
2475 }
2476 intravisit::walk_opaque_ty(self, opaque);
2477 }
2478 }
2479}
2480
2481fn deny_non_region_late_bound(
2482 tcx: TyCtxt<'_>,
2483 bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2484 where_: &str,
2485) {
2486 let mut first = true;
2487
2488 for (var, arg) in bound_vars {
2489 let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2490 span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2491 };
2492
2493 let what = match param.kind {
2494 hir::GenericParamKind::Type { .. } => "type",
2495 hir::GenericParamKind::Const { .. } => "const",
2496 hir::GenericParamKind::Lifetime { .. } => continue,
2497 };
2498
2499 let diag = tcx.dcx().struct_span_err(
2500 param.span,
2501 format!("late-bound {what} parameter not allowed on {where_}"),
2502 );
2503
2504 let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
2505
2506 first = false;
2507 *arg = ResolvedArg::Error(guar);
2508 }
2509}