1#![allow(rustc::diagnostic_outside_of_impl)]
15#![allow(rustc::untranslatable_diagnostic)]
16
17use std::cell::Cell;
18use std::iter;
19
20use rustc_data_structures::fx::FxIndexMap;
21use rustc_errors::Diag;
22use rustc_hir::BodyOwnerKind;
23use rustc_hir::def::DefKind;
24use rustc_hir::def_id::{DefId, LocalDefId};
25use rustc_hir::lang_items::LangItem;
26use rustc_index::IndexVec;
27use rustc_infer::infer::NllRegionVariableOrigin;
28use rustc_macros::extension;
29use rustc_middle::ty::print::with_no_trimmed_paths;
30use rustc_middle::ty::{
31 self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
32 TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
33};
34use rustc_middle::{bug, span_bug};
35use rustc_span::{ErrorGuaranteed, kw, sym};
36use tracing::{debug, instrument};
37
38use crate::BorrowckInferCtxt;
39use crate::renumber::RegionCtxt;
40
41#[derive(Debug)]
42#[derive(Clone)] pub(crate) struct UniversalRegions<'tcx> {
44 indices: UniversalRegionIndices<'tcx>,
45
46 pub fr_static: RegionVid,
48
49 pub fr_fn_body: RegionVid,
53
54 first_extern_index: usize,
61
62 first_local_index: usize,
64
65 num_universals: usize,
67
68 pub defining_ty: DefiningTy<'tcx>,
72
73 pub unnormalized_output_ty: Ty<'tcx>,
79
80 pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
86
87 pub yield_ty: Option<Ty<'tcx>>,
88
89 pub resume_ty: Option<Ty<'tcx>>,
90}
91
92#[derive(Copy, Clone, Debug)]
99pub(crate) enum DefiningTy<'tcx> {
100 Closure(DefId, GenericArgsRef<'tcx>),
103
104 Coroutine(DefId, GenericArgsRef<'tcx>),
108
109 CoroutineClosure(DefId, GenericArgsRef<'tcx>),
115
116 FnDef(DefId, GenericArgsRef<'tcx>),
119
120 Const(DefId, GenericArgsRef<'tcx>),
124
125 InlineConst(DefId, GenericArgsRef<'tcx>),
128
129 GlobalAsm(DefId),
133}
134
135impl<'tcx> DefiningTy<'tcx> {
136 pub(crate) fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
141 match self {
142 DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
143 DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
144 DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
145 DefiningTy::FnDef(..)
146 | DefiningTy::Const(..)
147 | DefiningTy::InlineConst(..)
148 | DefiningTy::GlobalAsm(_) => ty::List::empty(),
149 }
150 }
151
152 pub(crate) fn implicit_inputs(self) -> usize {
156 match self {
157 DefiningTy::Closure(..)
158 | DefiningTy::CoroutineClosure(..)
159 | DefiningTy::Coroutine(..) => 1,
160 DefiningTy::FnDef(..)
161 | DefiningTy::Const(..)
162 | DefiningTy::InlineConst(..)
163 | DefiningTy::GlobalAsm(_) => 0,
164 }
165 }
166
167 pub(crate) fn is_fn_def(&self) -> bool {
168 matches!(*self, DefiningTy::FnDef(..))
169 }
170
171 pub(crate) fn is_const(&self) -> bool {
172 matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
173 }
174
175 pub(crate) fn def_id(&self) -> DefId {
176 match *self {
177 DefiningTy::Closure(def_id, ..)
178 | DefiningTy::CoroutineClosure(def_id, ..)
179 | DefiningTy::Coroutine(def_id, ..)
180 | DefiningTy::FnDef(def_id, ..)
181 | DefiningTy::Const(def_id, ..)
182 | DefiningTy::InlineConst(def_id, ..)
183 | DefiningTy::GlobalAsm(def_id) => def_id,
184 }
185 }
186
187 pub(crate) fn args(&self) -> ty::GenericArgsRef<'tcx> {
190 match *self {
191 DefiningTy::Closure(_, args)
192 | DefiningTy::Coroutine(_, args)
193 | DefiningTy::CoroutineClosure(_, args)
194 | DefiningTy::FnDef(_, args)
195 | DefiningTy::Const(_, args)
196 | DefiningTy::InlineConst(_, args) => args,
197 DefiningTy::GlobalAsm(_) => ty::List::empty(),
198 }
199 }
200}
201
202#[derive(Debug)]
203#[derive(Clone)] struct UniversalRegionIndices<'tcx> {
205 indices: FxIndexMap<ty::Region<'tcx>, RegionVid>,
215
216 pub fr_static: RegionVid,
218
219 pub encountered_re_error: Cell<Option<ErrorGuaranteed>>,
222}
223
224#[derive(Debug, PartialEq)]
225pub(crate) enum RegionClassification {
226 Global,
229
230 External,
252
253 Local,
265}
266
267const FIRST_GLOBAL_INDEX: usize = 0;
268
269impl<'tcx> UniversalRegions<'tcx> {
270 pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
275 UniversalRegionsBuilder { infcx, mir_def }.build()
276 }
277
278 pub(crate) fn closure_mapping(
288 tcx: TyCtxt<'tcx>,
289 closure_args: GenericArgsRef<'tcx>,
290 expected_num_vars: usize,
291 closure_def_id: LocalDefId,
292 ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
293 let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
294 region_mapping.push(tcx.lifetimes.re_static);
295 tcx.for_each_free_region(&closure_args, |fr| {
296 region_mapping.push(fr);
297 });
298
299 for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
300 region_mapping.push(r);
301 });
302
303 assert_eq!(
304 region_mapping.len(),
305 expected_num_vars,
306 "index vec had unexpected number of variables"
307 );
308
309 region_mapping
310 }
311
312 pub(crate) fn is_universal_region(&self, r: RegionVid) -> bool {
314 (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index())
315 }
316
317 pub(crate) fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> {
320 let index = r.index();
321 if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) {
322 Some(RegionClassification::Global)
323 } else if (self.first_extern_index..self.first_local_index).contains(&index) {
324 Some(RegionClassification::External)
325 } else if (self.first_local_index..self.num_universals).contains(&index) {
326 Some(RegionClassification::Local)
327 } else {
328 None
329 }
330 }
331
332 pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> + 'static {
335 (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
336 }
337
338 pub(crate) fn is_local_free_region(&self, r: RegionVid) -> bool {
340 self.region_classification(r) == Some(RegionClassification::Local)
341 }
342
343 pub(crate) fn len(&self) -> usize {
345 self.num_universals
346 }
347
348 pub(crate) fn num_global_and_external_regions(&self) -> usize {
354 self.first_local_index
355 }
356
357 pub(crate) fn named_universal_regions_iter(
359 &self,
360 ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> {
361 self.indices.indices.iter().map(|(&r, &v)| (r, v))
362 }
363
364 pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
366 self.indices.to_region_vid(r)
367 }
368
369 pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
376 match self.defining_ty {
377 DefiningTy::Closure(def_id, args) => {
378 let v = with_no_trimmed_paths!(
379 args[tcx.generics_of(def_id).parent_count..]
380 .iter()
381 .map(|arg| arg.to_string())
382 .collect::<Vec<_>>()
383 );
384 err.note(format!(
385 "defining type: {} with closure args [\n {},\n]",
386 tcx.def_path_str_with_args(def_id, args),
387 v.join(",\n "),
388 ));
389
390 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
396 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
397 });
398 }
399 DefiningTy::CoroutineClosure(..) => {
400 todo!()
401 }
402 DefiningTy::Coroutine(def_id, args) => {
403 let v = with_no_trimmed_paths!(
404 args[tcx.generics_of(def_id).parent_count..]
405 .iter()
406 .map(|arg| arg.to_string())
407 .collect::<Vec<_>>()
408 );
409 err.note(format!(
410 "defining type: {} with coroutine args [\n {},\n]",
411 tcx.def_path_str_with_args(def_id, args),
412 v.join(",\n "),
413 ));
414
415 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
419 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
420 });
421 }
422 DefiningTy::FnDef(def_id, args) => {
423 err.note(format!("defining type: {}", tcx.def_path_str_with_args(def_id, args),));
424 }
425 DefiningTy::Const(def_id, args) => {
426 err.note(format!(
427 "defining constant type: {}",
428 tcx.def_path_str_with_args(def_id, args),
429 ));
430 }
431 DefiningTy::InlineConst(def_id, args) => {
432 err.note(format!(
433 "defining inline constant type: {}",
434 tcx.def_path_str_with_args(def_id, args),
435 ));
436 }
437 DefiningTy::GlobalAsm(_) => unreachable!(),
438 }
439 }
440
441 pub(crate) fn implicit_region_bound(&self) -> RegionVid {
442 self.fr_fn_body
443 }
444
445 pub(crate) fn encountered_re_error(&self) -> Option<ErrorGuaranteed> {
446 self.indices.encountered_re_error.get()
447 }
448}
449
450struct UniversalRegionsBuilder<'infcx, 'tcx> {
451 infcx: &'infcx BorrowckInferCtxt<'tcx>,
452 mir_def: LocalDefId,
453}
454
455impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
456 fn build(self) -> UniversalRegions<'tcx> {
457 debug!("build(mir_def={:?})", self.mir_def);
458
459 let param_env = self.infcx.param_env;
460 debug!("build: param_env={:?}", param_env);
461
462 assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
463
464 let fr_static = self
466 .infcx
467 .next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
468 RegionCtxt::Free(kw::Static)
469 })
470 .as_var();
471
472 let first_extern_index = self.infcx.num_region_vars();
475
476 let defining_ty = self.defining_ty();
477 debug!("build: defining_ty={:?}", defining_ty);
478
479 let mut indices = self.compute_indices(fr_static, defining_ty);
480 debug!("build: indices={:?}", indices);
481
482 let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
483
484 let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
488 first_extern_index
489 } else {
490 for_each_late_bound_region_in_recursive_scope(
497 self.infcx.tcx,
498 self.infcx.tcx.local_parent(self.mir_def),
499 |r| {
500 debug!(?r);
501 let region_vid = {
502 let name = r.get_name_or_anon(self.infcx.tcx);
503 self.infcx.next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
504 RegionCtxt::LateBound(name)
505 })
506 };
507
508 debug!(?region_vid);
509 indices.insert_late_bound_region(r, region_vid.as_var());
510 },
511 );
512
513 self.infcx.num_region_vars()
516 };
517
518 let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
525 for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
526 if let ty::BoundVariableKind::Region(kind) = bound_var {
527 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
528 let r = ty::Region::new_late_param(self.infcx.tcx, self.mir_def.to_def_id(), kind);
529 let region_vid = {
530 let name = r.get_name_or_anon(self.infcx.tcx);
531 self.infcx.next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
532 RegionCtxt::LateBound(name)
533 })
534 };
535
536 debug!(?region_vid);
537 indices.insert_late_bound_region(r, region_vid.as_var());
538 }
539 }
540 let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
541 self.mir_def,
542 bound_inputs_and_output,
543 &indices,
544 );
545
546 let (unnormalized_output_ty, mut unnormalized_input_tys) =
547 inputs_and_output.split_last().unwrap();
548
549 if let DefiningTy::FnDef(def_id, _) = defining_ty {
552 if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
553 let va_list_did = self
554 .infcx
555 .tcx
556 .require_lang_item(LangItem::VaList, self.infcx.tcx.def_span(self.mir_def));
557
558 let reg_vid = self
559 .infcx
560 .next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
561 RegionCtxt::Free(sym::c_dash_variadic)
562 })
563 .as_var();
564
565 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
566 let va_list_ty = self
567 .infcx
568 .tcx
569 .type_of(va_list_did)
570 .instantiate(self.infcx.tcx, &[region.into()]);
571
572 unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter(
573 unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
574 );
575 }
576 }
577
578 let fr_fn_body = self
579 .infcx
580 .next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
581 RegionCtxt::Free(sym::fn_body)
582 })
583 .as_var();
584
585 let num_universals = self.infcx.num_region_vars();
586
587 debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index);
588 debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
589 debug!("build: local regions = {}..{}", first_local_index, num_universals);
590
591 let (resume_ty, yield_ty) = match defining_ty {
592 DefiningTy::Coroutine(_, args) => {
593 let tys = args.as_coroutine();
594 (Some(tys.resume_ty()), Some(tys.yield_ty()))
595 }
596 _ => (None, None),
597 };
598
599 UniversalRegions {
600 indices,
601 fr_static,
602 fr_fn_body,
603 first_extern_index,
604 first_local_index,
605 num_universals,
606 defining_ty,
607 unnormalized_output_ty: *unnormalized_output_ty,
608 unnormalized_input_tys,
609 yield_ty,
610 resume_ty,
611 }
612 }
613
614 fn defining_ty(&self) -> DefiningTy<'tcx> {
617 let tcx = self.infcx.tcx;
618 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
619
620 match tcx.hir_body_owner_kind(self.mir_def) {
621 BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
622 let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
623
624 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
625
626 let defining_ty = self.infcx.replace_free_regions_with_nll_infer_vars(
627 NllRegionVariableOrigin::FreeRegion,
628 defining_ty,
629 );
630
631 match *defining_ty.kind() {
632 ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
633 ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args),
634 ty::CoroutineClosure(def_id, args) => {
635 DefiningTy::CoroutineClosure(def_id, args)
636 }
637 ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
638 _ => span_bug!(
639 tcx.def_span(self.mir_def),
640 "expected defining type for `{:?}`: `{:?}`",
641 self.mir_def,
642 defining_ty
643 ),
644 }
645 }
646
647 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
648 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
649 if self.mir_def.to_def_id() == typeck_root_def_id {
650 let args = self.infcx.replace_free_regions_with_nll_infer_vars(
651 NllRegionVariableOrigin::FreeRegion,
652 identity_args,
653 );
654 DefiningTy::Const(self.mir_def.to_def_id(), args)
655 } else {
656 let ty = tcx
666 .typeck(self.mir_def)
667 .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
668 let args = InlineConstArgs::new(
669 tcx,
670 InlineConstArgsParts { parent_args: identity_args, ty },
671 )
672 .args;
673 let args = self.infcx.replace_free_regions_with_nll_infer_vars(
674 NllRegionVariableOrigin::FreeRegion,
675 args,
676 );
677 DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
678 }
679 }
680
681 BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
682 }
683 }
684
685 fn compute_indices(
690 &self,
691 fr_static: RegionVid,
692 defining_ty: DefiningTy<'tcx>,
693 ) -> UniversalRegionIndices<'tcx> {
694 let tcx = self.infcx.tcx;
695 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
696 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
697 let renumbered_args = defining_ty.args();
698
699 let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
700 assert!(renumbered_args.len() >= identity_args.len());
703 let arg_mapping =
704 iter::zip(identity_args.regions(), renumbered_args.regions().map(|r| r.as_var()));
705
706 UniversalRegionIndices {
707 indices: global_mapping.chain(arg_mapping).collect(),
708 fr_static,
709 encountered_re_error: Cell::new(None),
710 }
711 }
712
713 fn compute_inputs_and_output(
714 &self,
715 indices: &UniversalRegionIndices<'tcx>,
716 defining_ty: DefiningTy<'tcx>,
717 ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
718 let tcx = self.infcx.tcx;
719
720 let inputs_and_output = match defining_ty {
721 DefiningTy::Closure(def_id, args) => {
722 assert_eq!(self.mir_def.to_def_id(), def_id);
723 let closure_sig = args.as_closure().sig();
724 let inputs_and_output = closure_sig.inputs_and_output();
725 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
726 inputs_and_output.bound_vars().iter().chain(iter::once(
727 ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
728 )),
729 );
730 let br = ty::BoundRegion {
731 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
732 kind: ty::BoundRegionKind::ClosureEnv,
733 };
734 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
735 let closure_ty = tcx.closure_env_ty(
736 Ty::new_closure(tcx, def_id, args),
737 args.as_closure().kind(),
738 env_region,
739 );
740
741 let (&output, tuplized_inputs) =
745 inputs_and_output.skip_binder().split_last().unwrap();
746 assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
747 let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else {
748 bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]);
749 };
750
751 ty::Binder::bind_with_vars(
752 tcx.mk_type_list_from_iter(
753 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
754 ),
755 bound_vars,
756 )
757 }
758
759 DefiningTy::Coroutine(def_id, args) => {
760 assert_eq!(self.mir_def.to_def_id(), def_id);
761 let resume_ty = args.as_coroutine().resume_ty();
762 let output = args.as_coroutine().return_ty();
763 let coroutine_ty = Ty::new_coroutine(tcx, def_id, args);
764 let inputs_and_output =
765 self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
766 ty::Binder::dummy(inputs_and_output)
767 }
768
769 DefiningTy::CoroutineClosure(def_id, args) => {
778 assert_eq!(self.mir_def.to_def_id(), def_id);
779 let closure_sig = args.as_coroutine_closure().coroutine_closure_sig();
780 let bound_vars =
781 tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain(
782 iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)),
783 ));
784 let br = ty::BoundRegion {
785 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
786 kind: ty::BoundRegionKind::ClosureEnv,
787 };
788 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
789 let closure_kind = args.as_coroutine_closure().kind();
790
791 let closure_ty = tcx.closure_env_ty(
792 Ty::new_coroutine_closure(tcx, def_id, args),
793 closure_kind,
794 env_region,
795 );
796
797 let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields();
798 let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars(
799 tcx,
800 args.as_coroutine_closure().parent_args(),
801 tcx.coroutine_for_closure(def_id),
802 closure_kind,
803 env_region,
804 args.as_coroutine_closure().tupled_upvars_ty(),
805 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
806 );
807
808 ty::Binder::bind_with_vars(
809 tcx.mk_type_list_from_iter(
810 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
811 ),
812 bound_vars,
813 )
814 }
815
816 DefiningTy::FnDef(def_id, _) => {
817 let sig = tcx.fn_sig(def_id).instantiate_identity();
818 let sig = indices.fold_to_region_vids(tcx, sig);
819 sig.inputs_and_output()
820 }
821
822 DefiningTy::Const(def_id, _) => {
823 assert_eq!(self.mir_def.to_def_id(), def_id);
826 let ty = tcx.type_of(self.mir_def).instantiate_identity();
827
828 let ty = indices.fold_to_region_vids(tcx, ty);
829 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
830 }
831
832 DefiningTy::InlineConst(def_id, args) => {
833 assert_eq!(self.mir_def.to_def_id(), def_id);
834 let ty = args.as_inline_const().ty();
835 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
836 }
837
838 DefiningTy::GlobalAsm(def_id) => {
839 ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
840 }
841 };
842
843 if let Err(e) = inputs_and_output.error_reported() {
845 self.infcx.set_tainted_by_errors(e);
846 }
847
848 inputs_and_output
849 }
850}
851
852#[extension(trait InferCtxtExt<'tcx>)]
853impl<'tcx> BorrowckInferCtxt<'tcx> {
854 #[instrument(skip(self), level = "debug")]
855 fn replace_free_regions_with_nll_infer_vars<T>(
856 &self,
857 origin: NllRegionVariableOrigin<'tcx>,
858 value: T,
859 ) -> T
860 where
861 T: TypeFoldable<TyCtxt<'tcx>>,
862 {
863 fold_regions(self.infcx.tcx, value, |region, _depth| {
864 let name = region.get_name_or_anon(self.infcx.tcx);
865 debug!(?region, ?name);
866
867 self.next_nll_region_var(origin, || RegionCtxt::Free(name))
868 })
869 }
870
871 #[instrument(level = "debug", skip(self, indices))]
872 fn replace_bound_regions_with_nll_infer_vars<T>(
873 &self,
874 all_outlive_scope: LocalDefId,
875 value: ty::Binder<'tcx, T>,
876 indices: &UniversalRegionIndices<'tcx>,
877 ) -> T
878 where
879 T: TypeFoldable<TyCtxt<'tcx>>,
880 {
881 let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
882 debug!(?br);
883 let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
884 let liberated_region =
885 ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
886 ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region))
887 });
888 value
889 }
890}
891
892impl<'tcx> UniversalRegionIndices<'tcx> {
893 fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
899 debug!("insert_late_bound_region({:?}, {:?})", r, vid);
900 assert_eq!(self.indices.insert(r, vid), None);
901 }
902
903 fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
916 match r.kind() {
917 ty::ReVar(..) => r.as_var(),
918 ty::ReError(guar) => {
919 self.encountered_re_error.set(Some(guar));
920 self.fr_static
924 }
925 _ => *self
926 .indices
927 .get(&r)
928 .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)),
929 }
930 }
931
932 fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
935 where
936 T: TypeFoldable<TyCtxt<'tcx>>,
937 {
938 fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
939 }
940}
941
942fn for_each_late_bound_region_in_recursive_scope<'tcx>(
946 tcx: TyCtxt<'tcx>,
947 mut mir_def_id: LocalDefId,
948 mut f: impl FnMut(ty::Region<'tcx>),
949) {
950 let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
951
952 loop {
954 for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
955
956 if mir_def_id.to_def_id() == typeck_root_def_id {
957 break;
958 } else {
959 mir_def_id = tcx.local_parent(mir_def_id);
960 }
961 }
962}
963
964fn for_each_late_bound_region_in_item<'tcx>(
968 tcx: TyCtxt<'tcx>,
969 mir_def_id: LocalDefId,
970 mut f: impl FnMut(ty::Region<'tcx>),
971) {
972 let bound_vars = match tcx.def_kind(mir_def_id) {
973 DefKind::Fn | DefKind::AssocFn => {
974 tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id))
975 }
976 DefKind::Closure => {
980 let ty = tcx.type_of(mir_def_id).instantiate_identity();
981 match *ty.kind() {
982 ty::Closure(_, args) => args.as_closure().sig().bound_vars(),
983 ty::CoroutineClosure(_, args) => {
984 args.as_coroutine_closure().coroutine_closure_sig().bound_vars()
985 }
986 ty::Coroutine(_, _) | ty::Error(_) => return,
987 _ => unreachable!("unexpected type for closure: {ty}"),
988 }
989 }
990 _ => return,
991 };
992
993 for (idx, bound_var) in bound_vars.iter().enumerate() {
994 if let ty::BoundVariableKind::Region(kind) = bound_var {
995 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
996 let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
997 f(liberated_region);
998 }
999 }
1000}