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 opaque_capture_errors: RefCell<Option<OpaqueHigherRankedLifetimeCaptureErrors>>,
70}
71
72struct OpaqueHigherRankedLifetimeCaptureErrors {
73 bad_place: &'static str,
74 capture_spans: Vec<Span>,
75 decl_spans: Vec<Span>,
76}
77
78#[derive(Debug)]
79enum Scope<'a> {
80 Binder {
85 bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
88
89 scope_type: BinderScopeType,
90
91 hir_id: HirId,
96
97 s: ScopeRef<'a>,
98
99 where_bound_origin: Option<hir::PredicateOrigin>,
105 },
106
107 Body {
112 id: hir::BodyId,
113 s: ScopeRef<'a>,
114 },
115
116 ObjectLifetimeDefault {
120 lifetime: Option<ResolvedArg>,
121 s: ScopeRef<'a>,
122 },
123
124 Supertrait {
129 bound_vars: Vec<ty::BoundVariableKind>,
130 s: ScopeRef<'a>,
131 },
132
133 TraitRefBoundary {
134 s: ScopeRef<'a>,
135 },
136
137 Opaque {
146 def_id: LocalDefId,
148 captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
150
151 s: ScopeRef<'a>,
152 },
153
154 LateBoundary {
160 s: ScopeRef<'a>,
161 what: &'static str,
162 deny_late_regions: bool,
163 },
164
165 Root {
166 opt_parent_item: Option<LocalDefId>,
167 },
168}
169
170impl<'a> Scope<'a> {
171 fn debug_truncated(&self) -> impl fmt::Debug {
173 fmt::from_fn(move |f| match self {
174 Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
175 .debug_struct("Binder")
176 .field("bound_vars", bound_vars)
177 .field("scope_type", scope_type)
178 .field("hir_id", hir_id)
179 .field("where_bound_origin", where_bound_origin)
180 .field("s", &"..")
181 .finish(),
182 Self::Opaque { captures, def_id, s: _ } => f
183 .debug_struct("Opaque")
184 .field("def_id", def_id)
185 .field("captures", &captures.borrow())
186 .field("s", &"..")
187 .finish(),
188 Self::Body { id, s: _ } => {
189 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
190 }
191 Self::ObjectLifetimeDefault { lifetime, s: _ } => f
192 .debug_struct("ObjectLifetimeDefault")
193 .field("lifetime", lifetime)
194 .field("s", &"..")
195 .finish(),
196 Self::Supertrait { bound_vars, s: _ } => f
197 .debug_struct("Supertrait")
198 .field("bound_vars", bound_vars)
199 .field("s", &"..")
200 .finish(),
201 Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
202 Self::LateBoundary { s: _, what, deny_late_regions } => f
203 .debug_struct("LateBoundary")
204 .field("what", what)
205 .field("deny_late_regions", deny_late_regions)
206 .finish(),
207 Self::Root { opt_parent_item } => {
208 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
209 }
210 })
211 }
212}
213
214#[derive(Copy, Clone, Debug)]
215enum BinderScopeType {
216 Normal,
218 Concatenating,
228}
229
230type ScopeRef<'a> = &'a Scope<'a>;
231
232pub(crate) fn provide(providers: &mut Providers) {
234 *providers = Providers {
235 resolve_bound_vars,
236
237 named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
238 is_late_bound_map,
239 object_lifetime_default,
240 late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
241 opaque_captured_lifetimes: |tcx, id| {
242 &tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
243 .opaque_captured_lifetimes
244 .get(&id)
245 .map_or(&[][..], |x| &x[..])
246 },
247
248 ..*providers
249 };
250}
251
252#[instrument(level = "debug", skip(tcx))]
256fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
257 let mut rbv = ResolveBoundVars::default();
258 let mut visitor = BoundVarContext {
259 tcx,
260 rbv: &mut rbv,
261 scope: &Scope::Root { opt_parent_item: None },
262 disambiguator: &mut DisambiguatorState::new(),
263 opaque_capture_errors: RefCell::new(None),
264 };
265 match tcx.hir_owner_node(local_def_id) {
266 hir::OwnerNode::Item(item) => visitor.visit_item(item),
267 hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
268 hir::OwnerNode::TraitItem(item) => {
269 let scope =
270 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
271 visitor.scope = &scope;
272 visitor.visit_trait_item(item)
273 }
274 hir::OwnerNode::ImplItem(item) => {
275 let scope =
276 Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
277 visitor.scope = &scope;
278 visitor.visit_impl_item(item)
279 }
280 hir::OwnerNode::Crate(_) => {}
281 hir::OwnerNode::Synthetic => unreachable!(),
282 }
283
284 debug!(?rbv.defs);
285 debug!(?rbv.late_bound_vars);
286 debug!(?rbv.opaque_captured_lifetimes);
287 rbv
288}
289
290fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind {
291 let def_id = param.def_id.to_def_id();
292 match param.kind {
293 GenericParamKind::Lifetime { .. } => {
294 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id))
295 }
296 GenericParamKind::Type { .. } => ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)),
297 GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
298 }
299}
300
301fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
305 match param.kind {
306 ty::GenericParamDefKind::Lifetime => {
307 ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id))
308 }
309 ty::GenericParamDefKind::Type { .. } => {
310 ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id))
311 }
312 ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
313 }
314}
315
316fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
320 match opaque.origin {
321 _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
324 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
325 _ if opaque.span.at_least_rust_2024() => true,
326 hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
327 }
328}
329
330impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
331 fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
333 let mut scope = self.scope;
334 let mut supertrait_bound_vars = vec![];
335 loop {
336 match scope {
337 Scope::Body { .. } | Scope::Root { .. } => {
338 break (vec![], BinderScopeType::Normal);
339 }
340
341 Scope::Opaque { s, .. }
342 | Scope::ObjectLifetimeDefault { s, .. }
343 | Scope::LateBoundary { s, .. } => {
344 scope = s;
345 }
346
347 Scope::Supertrait { s, bound_vars } => {
348 supertrait_bound_vars = bound_vars.clone();
349 scope = s;
350 }
351
352 Scope::TraitRefBoundary { .. } => {
353 if !supertrait_bound_vars.is_empty() {
357 self.tcx.dcx().delayed_bug(format!(
358 "found supertrait lifetimes without a binder to append \
359 them to: {supertrait_bound_vars:?}"
360 ));
361 }
362 break (vec![], BinderScopeType::Normal);
363 }
364
365 Scope::Binder { hir_id, .. } => {
366 let mut full_binders =
368 self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
369 full_binders.extend(supertrait_bound_vars);
370 break (full_binders, BinderScopeType::Concatenating);
371 }
372 }
373 }
374 }
375
376 fn visit_poly_trait_ref_inner(
377 &mut self,
378 trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
379 non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
380 ) {
381 debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
382
383 let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
384
385 let initial_bound_vars = binders.len() as u32;
386 let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
387 let binders_iter =
388 trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
389 let arg = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
390 bound_vars.insert(param.def_id, arg);
391 late_arg_as_bound_arg(param)
392 });
393 binders.extend(binders_iter);
394
395 if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
396 deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
397 }
398
399 debug!(?binders);
400 self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
401
402 let scope = Scope::Binder {
407 hir_id: trait_ref.trait_ref.hir_ref_id,
408 bound_vars,
409 s: self.scope,
410 scope_type,
411 where_bound_origin: None,
412 };
413 self.with(scope, |this| {
414 walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
415 this.visit_trait_ref(&trait_ref.trait_ref);
416 });
417 }
418}
419
420enum NonLifetimeBinderAllowed {
421 Deny(&'static str),
422 Allow,
423}
424
425impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
426 type NestedFilter = nested_filter::OnlyBodies;
427
428 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
429 self.tcx
430 }
431
432 fn visit_nested_body(&mut self, body: hir::BodyId) {
433 let body = self.tcx.hir_body(body);
434 self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
435 this.visit_body(body);
436 });
437 }
438
439 fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
440 if let hir::ExprKind::Closure(hir::Closure {
441 binder, bound_generic_params, fn_decl, ..
442 }) = e.kind
443 {
444 if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
445 fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
446 struct FindInferInClosureWithBinder;
449 impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
450 type Result = ControlFlow<Span>;
451
452 fn visit_infer(
453 &mut self,
454 _inf_id: HirId,
455 inf_span: Span,
456 _kind: InferKind<'v>,
457 ) -> Self::Result {
458 ControlFlow::Break(inf_span)
459 }
460 }
461 FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value()
462 }
463
464 let infer_in_rt_sp = match fn_decl.output {
465 hir::FnRetTy::DefaultReturn(sp) => Some(sp),
466 hir::FnRetTy::Return(ty) => span_of_infer(ty),
467 };
468
469 let infer_spans = fn_decl
470 .inputs
471 .into_iter()
472 .filter_map(span_of_infer)
473 .chain(infer_in_rt_sp)
474 .collect::<Vec<_>>();
475
476 if !infer_spans.is_empty() {
477 self.tcx
478 .dcx()
479 .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
480 }
481 }
482
483 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
484 bound_generic_params
485 .iter()
486 .enumerate()
487 .map(|(late_bound_idx, param)| {
488 (
489 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
490 late_arg_as_bound_arg(param),
491 )
492 })
493 .unzip();
494
495 deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
496
497 self.record_late_bound_vars(e.hir_id, binders);
498 let scope = Scope::Binder {
499 hir_id: e.hir_id,
500 bound_vars,
501 s: self.scope,
502 scope_type: BinderScopeType::Normal,
503 where_bound_origin: None,
504 };
505
506 self.with(scope, |this| {
507 intravisit::walk_expr(this, e)
510 });
511 } else {
512 intravisit::walk_expr(self, e)
513 }
514 }
515
516 #[instrument(level = "debug", skip(self))]
522 fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
523 let captures = RefCell::new(FxIndexMap::default());
524
525 let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
526 if capture_all_in_scope_lifetimes {
527 let tcx = self.tcx;
528 let lifetime_ident = |def_id: LocalDefId| {
529 let name = tcx.item_name(def_id.to_def_id());
530 let span = tcx.def_span(def_id);
531 Ident::new(name, span)
532 };
533
534 let mut late_depth = 0;
538 let mut scope = self.scope;
539 let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
540 loop {
541 match *scope {
542 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
543 for (&original_lifetime, &def) in bound_vars.iter().rev() {
544 if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
545 let def = def.shifted(late_depth);
546 let ident = lifetime_ident(original_lifetime);
547 self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
548 }
549 }
550 match scope_type {
551 BinderScopeType::Normal => late_depth += 1,
552 BinderScopeType::Concatenating => {}
553 }
554 scope = s;
555 }
556
557 Scope::Root { mut opt_parent_item } => {
558 while let Some(parent_item) = opt_parent_item {
559 let parent_generics = self.tcx.generics_of(parent_item);
560 for param in parent_generics.own_params.iter().rev() {
561 if let ty::GenericParamDefKind::Lifetime = param.kind {
562 let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
563 let ident = lifetime_ident(param.def_id.expect_local());
564 self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
565 }
566 }
567 opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
568 }
569 break;
570 }
571
572 Scope::Opaque { captures, def_id, s } => {
573 opaque_capture_scopes.push((def_id, captures));
574 late_depth = 0;
575 scope = s;
576 }
577
578 Scope::Body { .. } => {
579 bug!("{:?}", scope)
580 }
581
582 Scope::ObjectLifetimeDefault { s, .. }
583 | Scope::Supertrait { s, .. }
584 | Scope::TraitRefBoundary { s, .. }
585 | Scope::LateBoundary { s, .. } => {
586 scope = s;
587 }
588 }
589 }
590 captures.borrow_mut().reverse();
591 }
592
593 let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
594 self.with(scope, |this| {
595 let scope = Scope::TraitRefBoundary { s: this.scope };
596 this.with(scope, |this| {
597 let scope = Scope::LateBoundary {
598 s: this.scope,
599 what: "nested `impl Trait`",
600 deny_late_regions: false,
603 };
604 this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
605 })
606 });
607
608 self.emit_opaque_capture_errors();
609
610 let captures = captures.into_inner().into_iter().collect();
611 debug!(?captures);
612 self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
613 }
614
615 #[instrument(level = "debug", skip(self))]
616 fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
617 if let hir::ItemKind::Impl(impl_) = item.kind
618 && let Some(of_trait) = impl_.of_trait
619 {
620 self.record_late_bound_vars(of_trait.trait_ref.hir_ref_id, Vec::default());
621 }
622 match item.kind {
623 hir::ItemKind::Fn { generics, .. } => {
624 self.visit_early_late(item.hir_id(), generics, |this| {
625 intravisit::walk_item(this, item);
626 });
627 }
628
629 hir::ItemKind::ExternCrate(..)
630 | hir::ItemKind::Use(..)
631 | hir::ItemKind::Macro(..)
632 | hir::ItemKind::Mod(..)
633 | hir::ItemKind::ForeignMod { .. }
634 | hir::ItemKind::Static(..)
635 | hir::ItemKind::GlobalAsm { .. } => {
636 intravisit::walk_item(self, item);
638 }
639 hir::ItemKind::TyAlias(_, generics, _)
640 | hir::ItemKind::Const(_, generics, _, _)
641 | hir::ItemKind::Enum(_, generics, _)
642 | hir::ItemKind::Struct(_, generics, _)
643 | hir::ItemKind::Union(_, generics, _)
644 | hir::ItemKind::Trait(_, _, _, _, generics, ..)
645 | hir::ItemKind::TraitAlias(_, _, generics, ..)
646 | hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
647 self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
649 }
650 }
651 }
652
653 fn visit_precise_capturing_arg(
654 &mut self,
655 arg: &'tcx hir::PreciseCapturingArg<'tcx>,
656 ) -> Self::Result {
657 match *arg {
658 hir::PreciseCapturingArg::Lifetime(lt) => match lt.kind {
659 LifetimeKind::Param(def_id) => {
660 self.resolve_lifetime_ref(def_id, lt);
661 }
662 LifetimeKind::Error => {}
663 LifetimeKind::ImplicitObjectLifetimeDefault
664 | LifetimeKind::Infer
665 | LifetimeKind::Static => {
666 self.tcx.dcx().emit_err(errors::BadPreciseCapture {
667 span: lt.ident.span,
668 kind: "lifetime",
669 found: format!("`{}`", lt.ident.name),
670 });
671 }
672 },
673 hir::PreciseCapturingArg::Param(param) => match param.res {
674 Res::Def(DefKind::TyParam | DefKind::ConstParam, def_id)
675 | Res::SelfTyParam { trait_: def_id } => {
676 self.resolve_type_ref(def_id.expect_local(), param.hir_id);
677 }
678 Res::SelfTyAlias { alias_to, .. } => {
679 self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
680 span: param.ident.span,
681 self_span: self.tcx.def_span(alias_to),
682 what: self.tcx.def_descr(alias_to),
683 });
684 }
685 res => {
686 self.tcx.dcx().span_delayed_bug(
687 param.ident.span,
688 format!("expected type or const param, found {res:?}"),
689 );
690 }
691 },
692 }
693 }
694
695 fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
696 match item.kind {
697 hir::ForeignItemKind::Fn(_, _, generics) => {
698 self.visit_early_late(item.hir_id(), generics, |this| {
699 intravisit::walk_foreign_item(this, item);
700 })
701 }
702 hir::ForeignItemKind::Static(..) => {
703 intravisit::walk_foreign_item(self, item);
704 }
705 hir::ForeignItemKind::Type => {
706 intravisit::walk_foreign_item(self, item);
707 }
708 }
709 }
710
711 #[instrument(level = "debug", skip(self))]
712 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
713 match ty.kind {
714 hir::TyKind::FnPtr(c) => {
715 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
716 .generic_params
717 .iter()
718 .enumerate()
719 .map(|(late_bound_idx, param)| {
720 (
721 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
722 late_arg_as_bound_arg(param),
723 )
724 })
725 .unzip();
726
727 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
728
729 self.record_late_bound_vars(ty.hir_id, binders);
730 let scope = Scope::Binder {
731 hir_id: ty.hir_id,
732 bound_vars,
733 s: self.scope,
734 scope_type: BinderScopeType::Normal,
735 where_bound_origin: None,
736 };
737 self.with(scope, |this| {
738 intravisit::walk_ty(this, ty);
740 });
741 }
742 hir::TyKind::UnsafeBinder(binder) => {
743 let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
744 binder
745 .generic_params
746 .iter()
747 .enumerate()
748 .map(|(late_bound_idx, param)| {
749 (
750 (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
751 late_arg_as_bound_arg(param),
752 )
753 })
754 .unzip();
755
756 deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
757
758 self.record_late_bound_vars(ty.hir_id, binders);
759 let scope = Scope::Binder {
760 hir_id: ty.hir_id,
761 bound_vars,
762 s: self.scope,
763 scope_type: BinderScopeType::Normal,
764 where_bound_origin: None,
765 };
766 self.with(scope, |this| {
767 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(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 nested_errors = RefCell::new(self.opaque_capture_errors.borrow_mut().take());
1103 let mut this = BoundVarContext {
1104 tcx: *tcx,
1105 rbv,
1106 disambiguator,
1107 scope: &wrap_scope,
1108 opaque_capture_errors: nested_errors,
1109 };
1110 let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
1111 {
1112 let _enter = span.enter();
1113 f(&mut this);
1114 }
1115 *self.opaque_capture_errors.borrow_mut() = this.opaque_capture_errors.into_inner();
1116 }
1117
1118 fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
1119 if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
1120 bug!(
1121 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1122 self.rbv.late_bound_vars[&hir_id.local_id]
1123 )
1124 }
1125 }
1126
1127 fn visit_early_late<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1146 where
1147 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1148 {
1149 let mut named_late_bound_vars = 0;
1150 let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
1151 .params
1152 .iter()
1153 .map(|param| {
1154 (
1155 param.def_id,
1156 match param.kind {
1157 GenericParamKind::Lifetime { .. } => {
1158 if self.tcx.is_late_bound(param.hir_id) {
1159 let late_bound_idx = named_late_bound_vars;
1160 named_late_bound_vars += 1;
1161 ResolvedArg::late(late_bound_idx, param)
1162 } else {
1163 ResolvedArg::early(param)
1164 }
1165 }
1166 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1167 ResolvedArg::early(param)
1168 }
1169 },
1170 )
1171 })
1172 .collect();
1173
1174 let binders: Vec<_> = generics
1175 .params
1176 .iter()
1177 .filter(|param| {
1178 matches!(param.kind, GenericParamKind::Lifetime { .. })
1179 && self.tcx.is_late_bound(param.hir_id)
1180 })
1181 .map(|param| late_arg_as_bound_arg(param))
1182 .collect();
1183 self.record_late_bound_vars(hir_id, binders);
1184 let scope = Scope::Binder {
1185 hir_id,
1186 bound_vars,
1187 s: self.scope,
1188 scope_type: BinderScopeType::Normal,
1189 where_bound_origin: None,
1190 };
1191 self.with(scope, walk);
1192 }
1193
1194 fn visit_early<F>(&mut self, hir_id: HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
1195 where
1196 F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
1197 {
1198 let bound_vars =
1199 generics.params.iter().map(|param| (param.def_id, ResolvedArg::early(param))).collect();
1200 self.record_late_bound_vars(hir_id, vec![]);
1201 let scope = Scope::Binder {
1202 hir_id,
1203 bound_vars,
1204 s: self.scope,
1205 scope_type: BinderScopeType::Normal,
1206 where_bound_origin: None,
1207 };
1208 self.with(scope, |this| {
1209 let scope = Scope::TraitRefBoundary { s: this.scope };
1210 this.with(scope, walk)
1211 });
1212 }
1213
1214 #[instrument(level = "debug", skip(self))]
1215 fn resolve_lifetime_ref(
1216 &mut self,
1217 region_def_id: LocalDefId,
1218 lifetime_ref: &'tcx hir::Lifetime,
1219 ) {
1220 let mut late_depth = 0;
1225 let mut scope = self.scope;
1226 let mut outermost_body = None;
1227 let mut crossed_late_boundary = None;
1228 let mut opaque_capture_scopes = vec![];
1229 let result = loop {
1230 match *scope {
1231 Scope::Body { id, s } => {
1232 outermost_body = Some(id);
1233 scope = s;
1234 }
1235
1236 Scope::Root { opt_parent_item } => {
1237 if let Some(parent_item) = opt_parent_item
1238 && let parent_generics = self.tcx.generics_of(parent_item)
1239 && parent_generics
1240 .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
1241 .is_some()
1242 {
1243 break Some(ResolvedArg::EarlyBound(region_def_id));
1244 }
1245 break None;
1246 }
1247
1248 Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
1249 if let Some(&def) = bound_vars.get(®ion_def_id) {
1250 break Some(def.shifted(late_depth));
1251 }
1252 match scope_type {
1253 BinderScopeType::Normal => late_depth += 1,
1254 BinderScopeType::Concatenating => {}
1255 }
1256 if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
1259 && let hir::LifetimeKind::Param(param_id) = lifetime_ref.kind
1260 && let Some(generics) =
1261 self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
1262 && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
1263 && param.is_elided_lifetime()
1264 && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
1265 && !self.tcx.features().anonymous_lifetime_in_impl_trait()
1266 {
1267 let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
1268 &self.tcx.sess,
1269 sym::anonymous_lifetime_in_impl_trait,
1270 lifetime_ref.ident.span,
1271 "anonymous lifetimes in `impl Trait` are unstable",
1272 );
1273
1274 if let Some(generics) =
1275 self.tcx.hir_get_generics(lifetime_ref.hir_id.owner.def_id)
1276 {
1277 let new_param_sugg =
1278 if let Some(span) = generics.span_for_lifetime_suggestion() {
1279 (span, "'a, ".to_owned())
1280 } else {
1281 (generics.span, "<'a>".to_owned())
1282 };
1283
1284 let lifetime_sugg = lifetime_ref.suggestion("'a");
1285 let suggestions = vec![lifetime_sugg, new_param_sugg];
1286
1287 diag.span_label(
1288 lifetime_ref.ident.span,
1289 "expected named lifetime parameter",
1290 );
1291 diag.multipart_suggestion(
1292 "consider introducing a named lifetime parameter",
1293 suggestions,
1294 rustc_errors::Applicability::MaybeIncorrect,
1295 );
1296 }
1297
1298 diag.emit();
1299 return;
1300 }
1301 scope = s;
1302 }
1303
1304 Scope::Opaque { captures, def_id, s } => {
1305 opaque_capture_scopes.push((def_id, captures));
1306 late_depth = 0;
1307 scope = s;
1308 }
1309
1310 Scope::ObjectLifetimeDefault { s, .. }
1311 | Scope::Supertrait { s, .. }
1312 | Scope::TraitRefBoundary { s, .. } => {
1313 scope = s;
1314 }
1315
1316 Scope::LateBoundary { s, what, deny_late_regions } => {
1317 if deny_late_regions {
1318 crossed_late_boundary = Some(what);
1319 }
1320 scope = s;
1321 }
1322 }
1323 };
1324
1325 if let Some(mut def) = result {
1326 def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
1327
1328 if let ResolvedArg::EarlyBound(..) = def {
1329 } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
1331 && let Some(what) = crossed_late_boundary
1332 {
1333 let use_span = lifetime_ref.ident.span;
1334 let def_span = self.tcx.def_span(param_def_id);
1335 let guar = match self.tcx.def_kind(param_def_id) {
1336 DefKind::LifetimeParam => {
1337 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Lifetime {
1338 use_span,
1339 def_span,
1340 what,
1341 })
1342 }
1343 kind => span_bug!(
1344 use_span,
1345 "did not expect to resolve lifetime to {}",
1346 kind.descr(param_def_id.to_def_id())
1347 ),
1348 };
1349 def = ResolvedArg::Error(guar);
1350 } else if let Some(body_id) = outermost_body {
1351 let fn_id = self.tcx.hir_body_owner(body_id);
1352 match self.tcx.hir_node(fn_id) {
1353 Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn { .. }, .. })
1354 | Node::TraitItem(hir::TraitItem {
1355 owner_id,
1356 kind: hir::TraitItemKind::Fn(..),
1357 ..
1358 })
1359 | Node::ImplItem(hir::ImplItem {
1360 owner_id,
1361 kind: hir::ImplItemKind::Fn(..),
1362 ..
1363 }) => {
1364 def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
1365 }
1366 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
1367 def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
1368 }
1369 _ => {}
1370 }
1371 }
1372
1373 self.insert_lifetime(lifetime_ref, def);
1374 return;
1375 }
1376
1377 let mut scope = self.scope;
1387 loop {
1388 match *scope {
1389 Scope::Binder {
1390 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1391 } => {
1392 self.tcx.dcx().emit_err(errors::LateBoundInApit::Lifetime {
1393 span: lifetime_ref.ident.span,
1394 param_span: self.tcx.def_span(region_def_id),
1395 });
1396 return;
1397 }
1398 Scope::Root { .. } => break,
1399 Scope::Binder { s, .. }
1400 | Scope::Body { s, .. }
1401 | Scope::Opaque { s, .. }
1402 | Scope::ObjectLifetimeDefault { s, .. }
1403 | Scope::Supertrait { s, .. }
1404 | Scope::TraitRefBoundary { s, .. }
1405 | Scope::LateBoundary { s, .. } => {
1406 scope = s;
1407 }
1408 }
1409 }
1410
1411 self.tcx.dcx().span_delayed_bug(
1412 lifetime_ref.ident.span,
1413 format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
1414 );
1415 }
1416
1417 fn check_lifetime_is_capturable(
1422 &self,
1423 opaque_def_id: LocalDefId,
1424 lifetime: ResolvedArg,
1425 capture_span: Span,
1426 ) -> Result<(), ErrorGuaranteed> {
1427 let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
1428 let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
1429 let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
1430 hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
1433 hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
1435 hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(_), .. }) => {
1436 "higher-ranked lifetime from function pointer"
1437 }
1438 hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
1439 "higher-ranked lifetime from `dyn` type"
1440 }
1441 _ => "higher-ranked lifetime",
1442 };
1443
1444 let decl_span = self.tcx.def_span(lifetime_def_id);
1445 let opaque_span = self.tcx.def_span(opaque_def_id);
1446
1447 let mut errors = self.opaque_capture_errors.borrow_mut();
1448 let error_info = errors.get_or_insert_with(|| OpaqueHigherRankedLifetimeCaptureErrors {
1449 bad_place,
1450 capture_spans: Vec::new(),
1451 decl_spans: Vec::new(),
1452 });
1453
1454 if error_info.capture_spans.is_empty() {
1455 error_info.capture_spans.push(opaque_span);
1456 }
1457
1458 if capture_span != decl_span && capture_span != opaque_span {
1459 error_info.capture_spans.push(capture_span);
1460 }
1461
1462 if !error_info.decl_spans.contains(&decl_span) {
1463 error_info.decl_spans.push(decl_span);
1464 }
1465
1466 Err(self.tcx.dcx().span_delayed_bug(capture_span, "opaque capture error not emitted"))
1468 }
1469
1470 fn emit_opaque_capture_errors(&self) -> Option<ErrorGuaranteed> {
1471 let errors = self.opaque_capture_errors.borrow_mut().take()?;
1472 if errors.capture_spans.is_empty() {
1473 return None;
1474 }
1475
1476 let mut span = rustc_errors::MultiSpan::from_span(errors.capture_spans[0]);
1477 for &capture_span in &errors.capture_spans[1..] {
1478 span.push_span_label(capture_span, "");
1479 }
1480 let decl_span = rustc_errors::MultiSpan::from_spans(errors.decl_spans);
1481
1482 let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
1484 span,
1485 label: Some(errors.capture_spans[0]),
1486 decl_span,
1487 bad_place: errors.bad_place,
1488 });
1489
1490 Some(guar)
1491 }
1492
1493 #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
1494 fn remap_opaque_captures(
1495 &mut self,
1496 opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
1497 mut lifetime: ResolvedArg,
1498 ident: Ident,
1499 ) -> ResolvedArg {
1500 if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
1501 if let Err(guar) =
1502 self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
1503 {
1504 lifetime = ResolvedArg::Error(guar);
1505 }
1506 }
1507
1508 for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
1509 let mut captures = captures.borrow_mut();
1510 let remapped = *captures.entry(lifetime).or_insert_with(|| {
1511 let feed = self.tcx.create_def(
1516 opaque_def_id,
1517 None,
1518 DefKind::LifetimeParam,
1519 Some(DefPathData::OpaqueLifetime(ident.name)),
1520 &mut self.disambiguator,
1521 );
1522 feed.def_span(ident.span);
1523 feed.def_ident_span(Some(ident.span));
1524 feed.def_id()
1525 });
1526 lifetime = ResolvedArg::EarlyBound(remapped);
1527 }
1528 lifetime
1529 }
1530
1531 fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
1532 let mut late_depth = 0;
1537 let mut scope = self.scope;
1538 let mut crossed_late_boundary = None;
1539
1540 let result = loop {
1541 match *scope {
1542 Scope::Body { s, .. } => {
1543 scope = s;
1544 }
1545
1546 Scope::Root { opt_parent_item } => {
1547 if let Some(parent_item) = opt_parent_item
1548 && let parent_generics = self.tcx.generics_of(parent_item)
1549 && parent_generics
1550 .param_def_id_to_index(self.tcx, param_def_id.to_def_id())
1551 .is_some()
1552 {
1553 break Some(ResolvedArg::EarlyBound(param_def_id));
1554 }
1555 break None;
1556 }
1557
1558 Scope::Binder { ref bound_vars, scope_type, s, .. } => {
1559 if let Some(&def) = bound_vars.get(¶m_def_id) {
1560 break Some(def.shifted(late_depth));
1561 }
1562 match scope_type {
1563 BinderScopeType::Normal => late_depth += 1,
1564 BinderScopeType::Concatenating => {}
1565 }
1566 scope = s;
1567 }
1568
1569 Scope::ObjectLifetimeDefault { s, .. }
1570 | Scope::Opaque { s, .. }
1571 | Scope::Supertrait { s, .. }
1572 | Scope::TraitRefBoundary { s, .. } => {
1573 scope = s;
1574 }
1575
1576 Scope::LateBoundary { s, what, deny_late_regions: _ } => {
1577 crossed_late_boundary = Some(what);
1578 scope = s;
1579 }
1580 }
1581 };
1582
1583 if let Some(def) = result {
1584 if let ResolvedArg::LateBound(..) = def
1585 && let Some(what) = crossed_late_boundary
1586 {
1587 let use_span = self.tcx.hir_span(hir_id);
1588 let def_span = self.tcx.def_span(param_def_id);
1589 let guar = match self.tcx.def_kind(param_def_id) {
1590 DefKind::ConstParam => {
1591 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Const {
1592 use_span,
1593 def_span,
1594 what,
1595 })
1596 }
1597 DefKind::TyParam => {
1598 self.tcx.dcx().emit_err(errors::CannotCaptureLateBound::Type {
1599 use_span,
1600 def_span,
1601 what,
1602 })
1603 }
1604 kind => span_bug!(
1605 use_span,
1606 "did not expect to resolve non-lifetime param to {}",
1607 kind.descr(param_def_id.to_def_id())
1608 ),
1609 };
1610 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1611 } else {
1612 self.rbv.defs.insert(hir_id.local_id, def);
1613 }
1614 return;
1615 }
1616
1617 let mut scope = self.scope;
1627 loop {
1628 match *scope {
1629 Scope::Binder {
1630 where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1631 } => {
1632 let guar = self.tcx.dcx().emit_err(match self.tcx.def_kind(param_def_id) {
1633 DefKind::TyParam => errors::LateBoundInApit::Type {
1634 span: self.tcx.hir_span(hir_id),
1635 param_span: self.tcx.def_span(param_def_id),
1636 },
1637 DefKind::ConstParam => errors::LateBoundInApit::Const {
1638 span: self.tcx.hir_span(hir_id),
1639 param_span: self.tcx.def_span(param_def_id),
1640 },
1641 kind => {
1642 bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1643 }
1644 });
1645 self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
1646 return;
1647 }
1648 Scope::Root { .. } => break,
1649 Scope::Binder { s, .. }
1650 | Scope::Body { s, .. }
1651 | Scope::Opaque { s, .. }
1652 | Scope::ObjectLifetimeDefault { s, .. }
1653 | Scope::Supertrait { s, .. }
1654 | Scope::TraitRefBoundary { s, .. }
1655 | Scope::LateBoundary { s, .. } => {
1656 scope = s;
1657 }
1658 }
1659 }
1660
1661 self.tcx
1662 .dcx()
1663 .span_bug(self.tcx.hir_span(hir_id), format!("could not resolve {param_def_id:?}"));
1664 }
1665
1666 #[instrument(level = "debug", skip(self))]
1667 fn visit_segment_args(
1668 &mut self,
1669 res: Res,
1670 depth: usize,
1671 generic_args: &'tcx hir::GenericArgs<'tcx>,
1672 ) {
1673 if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
1674 self.visit_fn_like_elision(inputs, Some(output), false);
1675 return;
1676 }
1677
1678 for arg in generic_args.args {
1679 if let hir::GenericArg::Lifetime(lt) = arg {
1680 self.visit_lifetime(lt);
1681 }
1682 }
1683
1684 let type_def_id = match res {
1687 Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
1688 Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
1689 Res::Def(
1690 DefKind::Struct
1691 | DefKind::Union
1692 | DefKind::Enum
1693 | DefKind::TyAlias
1694 | DefKind::Trait,
1695 def_id,
1696 ) if depth == 0 => Some(def_id),
1697 _ => None,
1698 };
1699
1700 debug!(?type_def_id);
1701
1702 let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| {
1718 let in_body = {
1719 let mut scope = self.scope;
1720 loop {
1721 match *scope {
1722 Scope::Root { .. } => break false,
1723
1724 Scope::Body { .. } => break true,
1725
1726 Scope::Binder { s, .. }
1727 | Scope::ObjectLifetimeDefault { s, .. }
1728 | Scope::Opaque { s, .. }
1729 | Scope::Supertrait { s, .. }
1730 | Scope::TraitRefBoundary { s, .. }
1731 | Scope::LateBoundary { s, .. } => {
1732 scope = s;
1733 }
1734 }
1735 }
1736 };
1737
1738 let rbv = &self.rbv;
1739 let generics = self.tcx.generics_of(def_id);
1740
1741 debug_assert_eq!(generics.parent_count, 0);
1743
1744 let set_to_region = |set: ObjectLifetimeDefault| match set {
1745 ObjectLifetimeDefault::Empty => {
1746 if in_body {
1747 None
1748 } else {
1749 Some(ResolvedArg::StaticLifetime)
1750 }
1751 }
1752 ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
1753 ObjectLifetimeDefault::Param(param_def_id) => {
1754 let index = generics.param_def_id_to_index[¶m_def_id] as usize;
1756 generic_args.args.get(index).and_then(|arg| match arg {
1757 GenericArg::Lifetime(lt) => rbv.defs.get(<.hir_id.local_id).copied(),
1758 _ => None,
1759 })
1760 }
1761 ObjectLifetimeDefault::Ambiguous => None,
1762 };
1763 generics
1764 .own_params
1765 .iter()
1766 .filter_map(|param| {
1767 match self.tcx.def_kind(param.def_id) {
1768 DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
1773 DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
1774 DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
1777 dk => bug!("unexpected def_kind {:?}", dk),
1778 }
1779 })
1780 .map(set_to_region)
1781 .collect()
1782 });
1783
1784 debug!(?object_lifetime_defaults);
1785
1786 let mut i = 0;
1787 for arg in generic_args.args {
1788 match arg {
1789 GenericArg::Lifetime(_) => {}
1790 GenericArg::Type(ty) => {
1791 if let Some(<) = object_lifetime_defaults.get(i) {
1792 let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
1793 self.with(scope, |this| this.visit_ty(ty));
1794 } else {
1795 self.visit_ty(ty);
1796 }
1797 i += 1;
1798 }
1799 GenericArg::Const(ct) => {
1800 self.visit_const_arg(ct);
1801 i += 1;
1802 }
1803 GenericArg::Infer(inf) => {
1804 self.visit_id(inf.hir_id);
1805 i += 1;
1806 }
1807 }
1808 }
1809
1810 let has_lifetime_parameter =
1835 generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
1836
1837 for constraint in generic_args.constraints {
1840 let scope = Scope::ObjectLifetimeDefault {
1841 lifetime: if has_lifetime_parameter {
1842 None
1843 } else {
1844 Some(ResolvedArg::StaticLifetime)
1845 },
1846 s: self.scope,
1847 };
1848 if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
1862 {
1863 let bound_vars = if let Some(type_def_id) = type_def_id
1864 && self.tcx.def_kind(type_def_id) == DefKind::Trait
1865 && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
1866 self.tcx,
1867 type_def_id,
1868 constraint.ident,
1869 ty::AssocTag::Fn,
1870 ) {
1871 bound_vars.extend(
1872 self.tcx
1873 .generics_of(assoc_fn.def_id)
1874 .own_params
1875 .iter()
1876 .map(|param| generic_param_def_as_bound_arg(param)),
1877 );
1878 bound_vars.extend(
1879 self.tcx.fn_sig(assoc_fn.def_id).instantiate_identity().bound_vars(),
1880 );
1881 bound_vars
1882 } else {
1883 self.tcx
1884 .dcx()
1885 .span_delayed_bug(constraint.ident.span, "bad return type notation here");
1886 vec![]
1887 };
1888 self.with(scope, |this| {
1889 let scope = Scope::Supertrait { bound_vars, s: this.scope };
1890 this.with(scope, |this| {
1891 let (bound_vars, _) = this.poly_trait_ref_binder_info();
1892 this.record_late_bound_vars(constraint.hir_id, bound_vars);
1893 this.visit_assoc_item_constraint(constraint)
1894 });
1895 });
1896 } else if let Some(type_def_id) = type_def_id {
1897 let bound_vars = BoundVarContext::supertrait_hrtb_vars(
1898 self.tcx,
1899 type_def_id,
1900 constraint.ident,
1901 ty::AssocTag::Type,
1902 )
1903 .map(|(bound_vars, _)| bound_vars);
1904 self.with(scope, |this| {
1905 let scope = Scope::Supertrait {
1906 bound_vars: bound_vars.unwrap_or_default(),
1907 s: this.scope,
1908 };
1909 this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1910 });
1911 } else {
1912 self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
1913 }
1914 }
1915 }
1916
1917 fn supertrait_hrtb_vars(
1930 tcx: TyCtxt<'tcx>,
1931 def_id: DefId,
1932 assoc_ident: Ident,
1933 assoc_tag: ty::AssocTag,
1934 ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
1935 let trait_defines_associated_item_named = |trait_def_id: DefId| {
1936 tcx.associated_items(trait_def_id).find_by_ident_and_kind(
1937 tcx,
1938 assoc_ident,
1939 assoc_tag,
1940 trait_def_id,
1941 )
1942 };
1943
1944 use smallvec::{SmallVec, smallvec};
1945 let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
1946 smallvec![(def_id, smallvec![])];
1947 let mut visited: FxHashSet<DefId> = FxHashSet::default();
1948 loop {
1949 let Some((def_id, bound_vars)) = stack.pop() else {
1950 break None;
1951 };
1952 match tcx.def_kind(def_id) {
1955 DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
1956 _ => break None,
1957 }
1958
1959 if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
1960 break Some((bound_vars.into_iter().collect(), assoc_item));
1961 }
1962 let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_ident));
1963 let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| {
1964 let bound_predicate = pred.kind();
1965 match bound_predicate.skip_binder() {
1966 ty::ClauseKind::Trait(data) => {
1967 let pred_bound_vars = bound_predicate.bound_vars();
1970 let mut all_bound_vars = bound_vars.clone();
1971 all_bound_vars.extend(pred_bound_vars.iter());
1972 let super_def_id = data.trait_ref.def_id;
1973 Some((super_def_id, all_bound_vars))
1974 }
1975 _ => None,
1976 }
1977 });
1978
1979 let obligations = obligations.filter(|o| visited.insert(o.0));
1980 stack.extend(obligations);
1981 }
1982 }
1983
1984 #[instrument(level = "debug", skip(self))]
1985 fn visit_fn_like_elision(
1986 &mut self,
1987 inputs: &'tcx [hir::Ty<'tcx>],
1988 output: Option<&'tcx hir::Ty<'tcx>>,
1989 in_closure: bool,
1990 ) {
1991 self.with(
1992 Scope::ObjectLifetimeDefault {
1993 lifetime: Some(ResolvedArg::StaticLifetime),
1994 s: self.scope,
1995 },
1996 |this| {
1997 for input in inputs {
1998 this.visit_ty_unambig(input);
1999 }
2000 if !in_closure && let Some(output) = output {
2001 this.visit_ty_unambig(output);
2002 }
2003 },
2004 );
2005 if in_closure && let Some(output) = output {
2006 self.visit_ty_unambig(output);
2007 }
2008 }
2009
2010 #[instrument(level = "debug", skip(self))]
2011 fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2012 let mut late_depth = 0;
2013 let mut scope = self.scope;
2014 let mut opaque_capture_scopes = vec![];
2015 let mut lifetime = loop {
2016 match *scope {
2017 Scope::Binder { s, scope_type, .. } => {
2018 match scope_type {
2019 BinderScopeType::Normal => late_depth += 1,
2020 BinderScopeType::Concatenating => {}
2021 }
2022 scope = s;
2023 }
2024
2025 Scope::Root { .. } => break ResolvedArg::StaticLifetime,
2026
2027 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
2028
2029 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
2030 break l.shifted(late_depth);
2031 }
2032
2033 Scope::Opaque { captures, def_id, s } => {
2034 opaque_capture_scopes.push((def_id, captures));
2035 late_depth = 0;
2036 scope = s;
2037 }
2038
2039 Scope::Supertrait { s, .. }
2040 | Scope::TraitRefBoundary { s, .. }
2041 | Scope::LateBoundary { s, .. } => {
2042 scope = s;
2043 }
2044 }
2045 };
2046
2047 lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
2048
2049 self.insert_lifetime(lifetime_ref, lifetime);
2050 }
2051
2052 #[instrument(level = "debug", skip(self))]
2053 fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
2054 debug!(span = ?lifetime_ref.ident.span);
2055 self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
2056 }
2057
2058 fn try_append_return_type_notation_params(
2077 &mut self,
2078 hir_id: HirId,
2079 hir_ty: &'tcx hir::Ty<'tcx>,
2080 ) {
2081 let hir::TyKind::Path(qpath) = hir_ty.kind else {
2082 return;
2086 };
2087
2088 let (mut bound_vars, item_def_id, item_segment) = match qpath {
2089 hir::QPath::Resolved(_, path)
2091 if let [.., item_segment] = &path.segments[..]
2092 && item_segment.args.is_some_and(|args| {
2093 matches!(
2094 args.parenthesized,
2095 hir::GenericArgsParentheses::ReturnTypeNotation
2096 )
2097 }) =>
2098 {
2099 match path.res {
2100 Res::Err => return,
2101 Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
2102 _ => bug!("only expected method resolution for fully qualified RTN"),
2103 }
2104 }
2105
2106 hir::QPath::TypeRelative(qself, item_segment)
2108 if item_segment.args.is_some_and(|args| {
2109 matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
2110 }) =>
2111 {
2112 let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
2115 return;
2116 };
2117 match path.res {
2118 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
2119 let mut bounds =
2120 self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| {
2121 BoundVarContext::supertrait_hrtb_vars(
2122 self.tcx,
2123 trait_def_id,
2124 item_segment.ident,
2125 ty::AssocTag::Fn,
2126 )
2127 });
2128
2129 let Some((bound_vars, assoc_item)) = bounds.next() else {
2130 self.tcx
2132 .dcx()
2133 .span_delayed_bug(path.span, "no resolution for RTN path");
2134 return;
2135 };
2136
2137 for (second_vars, second_assoc_item) in bounds {
2140 if second_vars != bound_vars || second_assoc_item != assoc_item {
2141 self.tcx.dcx().span_delayed_bug(
2143 path.span,
2144 "ambiguous resolution for RTN path",
2145 );
2146 return;
2147 }
2148 }
2149
2150 (bound_vars, assoc_item.def_id, item_segment)
2151 }
2152 Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
2155 let hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = self
2156 .tcx
2157 .hir_node_by_def_id(impl_def_id.expect_local())
2158 .expect_item()
2159 .kind
2160 else {
2161 return;
2162 };
2163 let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
2164 return;
2165 };
2166 let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
2167 self.tcx,
2168 trait_def_id,
2169 item_segment.ident,
2170 ty::AssocTag::Fn,
2171 ) else {
2172 return;
2173 };
2174 (bound_vars, assoc_item.def_id, item_segment)
2175 }
2176 _ => return,
2177 }
2178 }
2179
2180 _ => return,
2181 };
2182
2183 bound_vars.extend(
2187 self.tcx
2188 .generics_of(item_def_id)
2189 .own_params
2190 .iter()
2191 .map(|param| generic_param_def_as_bound_arg(param)),
2192 );
2193 bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
2194
2195 let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
2211 let existing_bound_vars_saved = existing_bound_vars.clone();
2212 existing_bound_vars.extend(bound_vars);
2213 self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
2214 }
2215
2216 fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
2219 gen move {
2220 let mut scope = self.scope;
2221 loop {
2222 let hir_id = match *scope {
2223 Scope::Binder { hir_id, .. } => Some(hir_id),
2224 Scope::Root { opt_parent_item: Some(parent_def_id) } => {
2225 Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
2226 }
2227 Scope::Body { .. }
2228 | Scope::ObjectLifetimeDefault { .. }
2229 | Scope::Supertrait { .. }
2230 | Scope::TraitRefBoundary { .. }
2231 | Scope::LateBoundary { .. }
2232 | Scope::Opaque { .. }
2233 | Scope::Root { opt_parent_item: None } => None,
2234 };
2235
2236 if let Some(hir_id) = hir_id {
2237 let node = self.tcx.hir_node(hir_id);
2238 if let Res::SelfTyParam { trait_: _ } = expected_res
2242 && let hir::Node::Item(item) = node
2243 && let hir::ItemKind::Trait(..) = item.kind
2244 {
2245 yield item.owner_id.def_id.to_def_id();
2248 } else if let Some(generics) = node.generics() {
2249 for pred in generics.predicates {
2250 let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
2251 continue;
2252 };
2253 let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
2254 pred.bounded_ty.kind
2255 else {
2256 continue;
2257 };
2258 if bounded_path.res != expected_res {
2260 continue;
2261 }
2262 for pred in pred.bounds {
2263 match pred {
2264 hir::GenericBound::Trait(poly_trait_ref) => {
2265 if let Some(def_id) =
2266 poly_trait_ref.trait_ref.trait_def_id()
2267 {
2268 yield def_id;
2269 }
2270 }
2271 hir::GenericBound::Outlives(_)
2272 | hir::GenericBound::Use(_, _) => {}
2273 }
2274 }
2275 }
2276 }
2277 }
2278
2279 match *scope {
2280 Scope::Binder { s, .. }
2281 | Scope::Body { s, .. }
2282 | Scope::ObjectLifetimeDefault { s, .. }
2283 | Scope::Supertrait { s, .. }
2284 | Scope::TraitRefBoundary { s }
2285 | Scope::LateBoundary { s, .. }
2286 | Scope::Opaque { s, .. } => {
2287 scope = s;
2288 }
2289 Scope::Root { .. } => break,
2290 }
2291 }
2292 }
2293 }
2294}
2295
2296fn is_late_bound_map(
2307 tcx: TyCtxt<'_>,
2308 owner_id: hir::OwnerId,
2309) -> Option<&FxIndexSet<hir::ItemLocalId>> {
2310 let sig = tcx.hir_fn_sig_by_hir_id(owner_id.into())?;
2311 let generics = tcx.hir_get_generics(owner_id.def_id)?;
2312
2313 let mut late_bound = FxIndexSet::default();
2314
2315 let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
2316 for arg_ty in sig.decl.inputs {
2317 constrained_by_input.visit_ty_unambig(arg_ty);
2318 }
2319
2320 let mut appears_in_output =
2321 AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
2322 intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
2323 if appears_in_output.has_fully_capturing_opaque {
2324 appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
2325 }
2326
2327 debug!(?constrained_by_input.regions);
2328
2329 let mut appears_in_where_clause =
2334 AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
2335 appears_in_where_clause.visit_generics(generics);
2336 debug!(?appears_in_where_clause.regions);
2337
2338 for param in generics.params {
2343 match param.kind {
2344 hir::GenericParamKind::Lifetime { .. } => { }
2345
2346 hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
2348 }
2349
2350 if appears_in_where_clause.regions.contains(¶m.def_id) {
2352 continue;
2353 }
2354
2355 if !constrained_by_input.regions.contains(¶m.def_id)
2357 && appears_in_output.regions.contains(¶m.def_id)
2358 {
2359 continue;
2360 }
2361
2362 debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
2363
2364 let inserted = late_bound.insert(param.hir_id.local_id);
2365 assert!(inserted, "visited lifetime {:?} twice", param.def_id);
2366 }
2367
2368 debug!(?late_bound);
2369 return Some(tcx.arena.alloc(late_bound));
2370
2371 struct ConstrainedCollectorPostHirTyLowering {
2393 arg_is_constrained: Box<[bool]>,
2394 }
2395
2396 use ty::Ty;
2397 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostHirTyLowering {
2398 fn visit_ty(&mut self, t: Ty<'tcx>) {
2399 match t.kind() {
2400 ty::Param(param_ty) => {
2401 self.arg_is_constrained[param_ty.index as usize] = true;
2402 }
2403 ty::Alias(ty::Projection | ty::Inherent, _) => return,
2404 _ => (),
2405 }
2406 t.super_visit_with(self)
2407 }
2408
2409 fn visit_const(&mut self, _: ty::Const<'tcx>) {}
2410
2411 fn visit_region(&mut self, r: ty::Region<'tcx>) {
2412 debug!("r={:?}", r.kind());
2413 if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
2414 self.arg_is_constrained[region.index as usize] = true;
2415 }
2416 }
2417 }
2418
2419 struct ConstrainedCollector<'tcx> {
2420 tcx: TyCtxt<'tcx>,
2421 regions: FxHashSet<LocalDefId>,
2422 }
2423
2424 impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
2425 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
2426 match ty.kind {
2427 hir::TyKind::Path(
2428 hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),
2429 ) => {
2430 }
2434
2435 hir::TyKind::Path(hir::QPath::Resolved(
2436 None,
2437 hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
2438 )) => {
2439 let generics = self.tcx.generics_of(alias_def);
2442 let mut walker = ConstrainedCollectorPostHirTyLowering {
2443 arg_is_constrained: vec![false; generics.own_params.len()]
2444 .into_boxed_slice(),
2445 };
2446 walker.visit_ty(self.tcx.type_of(alias_def).instantiate_identity());
2447
2448 match segments.last() {
2449 Some(hir::PathSegment { args: Some(args), .. }) => {
2450 let tcx = self.tcx;
2451 for constrained_arg in
2452 args.args.iter().enumerate().flat_map(|(n, arg)| {
2453 match walker.arg_is_constrained.get(n) {
2454 Some(true) => Some(arg),
2455 Some(false) => None,
2456 None => {
2457 tcx.dcx().span_delayed_bug(
2458 *span,
2459 format!(
2460 "Incorrect generic arg count for alias {alias_def:?}"
2461 ),
2462 );
2463 None
2464 }
2465 }
2466 })
2467 {
2468 self.visit_generic_arg(constrained_arg);
2469 }
2470 }
2471 Some(_) => (),
2472 None => bug!("Path with no segments or self type"),
2473 }
2474 }
2475
2476 hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
2477 if let Some(last_segment) = path.segments.last() {
2483 self.visit_path_segment(last_segment);
2484 }
2485 }
2486
2487 _ => {
2488 intravisit::walk_ty(self, ty);
2489 }
2490 }
2491 }
2492
2493 fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
2494 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2495 self.regions.insert(def_id);
2496 }
2497 }
2498 }
2499
2500 struct AllCollector {
2501 has_fully_capturing_opaque: bool,
2502 regions: FxHashSet<LocalDefId>,
2503 }
2504
2505 impl<'tcx> Visitor<'tcx> for AllCollector {
2506 fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2507 if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
2508 self.regions.insert(def_id);
2509 }
2510 }
2511
2512 fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
2513 if !self.has_fully_capturing_opaque {
2514 self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
2515 }
2516 intravisit::walk_opaque_ty(self, opaque);
2517 }
2518 }
2519}
2520
2521fn deny_non_region_late_bound(
2522 tcx: TyCtxt<'_>,
2523 bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
2524 where_: &str,
2525) {
2526 let mut first = true;
2527
2528 for (var, arg) in bound_vars {
2529 let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else {
2530 span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param");
2531 };
2532
2533 let what = match param.kind {
2534 hir::GenericParamKind::Type { .. } => "type",
2535 hir::GenericParamKind::Const { .. } => "const",
2536 hir::GenericParamKind::Lifetime { .. } => continue,
2537 };
2538
2539 let diag = tcx.dcx().struct_span_err(
2540 param.span,
2541 format!("late-bound {what} parameter not allowed on {where_}"),
2542 );
2543
2544 let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first);
2545
2546 first = false;
2547 *arg = ResolvedArg::Error(guar);
2548 }
2549}