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, unnormalized_input_tys) =
547 inputs_and_output.split_last().unwrap();
548
549 let fr_fn_body = self
550 .infcx
551 .next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
552 RegionCtxt::Free(sym::fn_body)
553 })
554 .as_var();
555
556 let num_universals = self.infcx.num_region_vars();
557
558 debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index);
559 debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
560 debug!("build: local regions = {}..{}", first_local_index, num_universals);
561
562 let (resume_ty, yield_ty) = match defining_ty {
563 DefiningTy::Coroutine(_, args) => {
564 let tys = args.as_coroutine();
565 (Some(tys.resume_ty()), Some(tys.yield_ty()))
566 }
567 _ => (None, None),
568 };
569
570 UniversalRegions {
571 indices,
572 fr_static,
573 fr_fn_body,
574 first_extern_index,
575 first_local_index,
576 num_universals,
577 defining_ty,
578 unnormalized_output_ty: *unnormalized_output_ty,
579 unnormalized_input_tys,
580 yield_ty,
581 resume_ty,
582 }
583 }
584
585 fn defining_ty(&self) -> DefiningTy<'tcx> {
588 let tcx = self.infcx.tcx;
589 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
590
591 match tcx.hir_body_owner_kind(self.mir_def) {
592 BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
593 let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
594
595 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
596
597 let defining_ty = self.infcx.replace_free_regions_with_nll_infer_vars(
598 NllRegionVariableOrigin::FreeRegion,
599 defining_ty,
600 );
601
602 match *defining_ty.kind() {
603 ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
604 ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args),
605 ty::CoroutineClosure(def_id, args) => {
606 DefiningTy::CoroutineClosure(def_id, args)
607 }
608 ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
609 _ => span_bug!(
610 tcx.def_span(self.mir_def),
611 "expected defining type for `{:?}`: `{:?}`",
612 self.mir_def,
613 defining_ty
614 ),
615 }
616 }
617
618 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
619 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
620 if self.mir_def.to_def_id() == typeck_root_def_id {
621 let args = self.infcx.replace_free_regions_with_nll_infer_vars(
622 NllRegionVariableOrigin::FreeRegion,
623 identity_args,
624 );
625 DefiningTy::Const(self.mir_def.to_def_id(), args)
626 } else {
627 let ty = tcx
637 .typeck(self.mir_def)
638 .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
639 let args = InlineConstArgs::new(
640 tcx,
641 InlineConstArgsParts { parent_args: identity_args, ty },
642 )
643 .args;
644 let args = self.infcx.replace_free_regions_with_nll_infer_vars(
645 NllRegionVariableOrigin::FreeRegion,
646 args,
647 );
648 DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
649 }
650 }
651
652 BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
653 }
654 }
655
656 fn compute_indices(
661 &self,
662 fr_static: RegionVid,
663 defining_ty: DefiningTy<'tcx>,
664 ) -> UniversalRegionIndices<'tcx> {
665 let tcx = self.infcx.tcx;
666 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
667 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
668 let renumbered_args = defining_ty.args();
669
670 let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
671 assert!(renumbered_args.len() >= identity_args.len());
674 let arg_mapping =
675 iter::zip(identity_args.regions(), renumbered_args.regions().map(|r| r.as_var()));
676
677 UniversalRegionIndices {
678 indices: global_mapping.chain(arg_mapping).collect(),
679 fr_static,
680 encountered_re_error: Cell::new(None),
681 }
682 }
683
684 fn compute_inputs_and_output(
685 &self,
686 indices: &UniversalRegionIndices<'tcx>,
687 defining_ty: DefiningTy<'tcx>,
688 ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
689 let tcx = self.infcx.tcx;
690
691 let inputs_and_output = match defining_ty {
692 DefiningTy::Closure(def_id, args) => {
693 assert_eq!(self.mir_def.to_def_id(), def_id);
694 let closure_sig = args.as_closure().sig();
695 let inputs_and_output = closure_sig.inputs_and_output();
696 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
697 inputs_and_output.bound_vars().iter().chain(iter::once(
698 ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
699 )),
700 );
701 let br = ty::BoundRegion {
702 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
703 kind: ty::BoundRegionKind::ClosureEnv,
704 };
705 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
706 let closure_ty = tcx.closure_env_ty(
707 Ty::new_closure(tcx, def_id, args),
708 args.as_closure().kind(),
709 env_region,
710 );
711
712 let (&output, tuplized_inputs) =
716 inputs_and_output.skip_binder().split_last().unwrap();
717 assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
718 let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else {
719 bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]);
720 };
721
722 ty::Binder::bind_with_vars(
723 tcx.mk_type_list_from_iter(
724 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
725 ),
726 bound_vars,
727 )
728 }
729
730 DefiningTy::Coroutine(def_id, args) => {
731 assert_eq!(self.mir_def.to_def_id(), def_id);
732 let resume_ty = args.as_coroutine().resume_ty();
733 let output = args.as_coroutine().return_ty();
734 let coroutine_ty = Ty::new_coroutine(tcx, def_id, args);
735 let inputs_and_output =
736 self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
737 ty::Binder::dummy(inputs_and_output)
738 }
739
740 DefiningTy::CoroutineClosure(def_id, args) => {
749 assert_eq!(self.mir_def.to_def_id(), def_id);
750 let closure_sig = args.as_coroutine_closure().coroutine_closure_sig();
751 let bound_vars =
752 tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain(
753 iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)),
754 ));
755 let br = ty::BoundRegion {
756 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
757 kind: ty::BoundRegionKind::ClosureEnv,
758 };
759 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
760 let closure_kind = args.as_coroutine_closure().kind();
761
762 let closure_ty = tcx.closure_env_ty(
763 Ty::new_coroutine_closure(tcx, def_id, args),
764 closure_kind,
765 env_region,
766 );
767
768 let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields();
769 let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars(
770 tcx,
771 args.as_coroutine_closure().parent_args(),
772 tcx.coroutine_for_closure(def_id),
773 closure_kind,
774 env_region,
775 args.as_coroutine_closure().tupled_upvars_ty(),
776 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
777 );
778
779 ty::Binder::bind_with_vars(
780 tcx.mk_type_list_from_iter(
781 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
782 ),
783 bound_vars,
784 )
785 }
786
787 DefiningTy::FnDef(def_id, _) => {
788 let sig = tcx.fn_sig(def_id).instantiate_identity();
789 let sig = indices.fold_to_region_vids(tcx, sig);
790 let inputs_and_output = sig.inputs_and_output();
791
792 if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
795 let va_list_did = self
796 .infcx
797 .tcx
798 .require_lang_item(LangItem::VaList, self.infcx.tcx.def_span(self.mir_def));
799
800 let reg_vid = self
801 .infcx
802 .next_nll_region_var(NllRegionVariableOrigin::FreeRegion, || {
803 RegionCtxt::Free(sym::c_dash_variadic)
804 })
805 .as_var();
806
807 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
808 let va_list_ty = self
809 .infcx
810 .tcx
811 .type_of(va_list_did)
812 .instantiate(self.infcx.tcx, &[region.into()]);
813
814 return inputs_and_output.map_bound(|tys| {
816 let (output_ty, input_tys) = tys.split_last().unwrap();
817 tcx.mk_type_list_from_iter(
818 input_tys.iter().copied().chain([va_list_ty, *output_ty]),
819 )
820 });
821 }
822
823 inputs_and_output
824 }
825
826 DefiningTy::Const(def_id, _) => {
827 assert_eq!(self.mir_def.to_def_id(), def_id);
830 let ty = tcx.type_of(self.mir_def).instantiate_identity();
831
832 let ty = indices.fold_to_region_vids(tcx, ty);
833 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
834 }
835
836 DefiningTy::InlineConst(def_id, args) => {
837 assert_eq!(self.mir_def.to_def_id(), def_id);
838 let ty = args.as_inline_const().ty();
839 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
840 }
841
842 DefiningTy::GlobalAsm(def_id) => {
843 ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
844 }
845 };
846
847 if let Err(e) = inputs_and_output.error_reported() {
849 self.infcx.set_tainted_by_errors(e);
850 }
851
852 inputs_and_output
853 }
854}
855
856#[extension(trait InferCtxtExt<'tcx>)]
857impl<'tcx> BorrowckInferCtxt<'tcx> {
858 #[instrument(skip(self), level = "debug")]
859 fn replace_free_regions_with_nll_infer_vars<T>(
860 &self,
861 origin: NllRegionVariableOrigin<'tcx>,
862 value: T,
863 ) -> T
864 where
865 T: TypeFoldable<TyCtxt<'tcx>>,
866 {
867 fold_regions(self.infcx.tcx, value, |region, _depth| {
868 let name = region.get_name_or_anon(self.infcx.tcx);
869 debug!(?region, ?name);
870
871 self.next_nll_region_var(origin, || RegionCtxt::Free(name))
872 })
873 }
874
875 #[instrument(level = "debug", skip(self, indices))]
876 fn replace_bound_regions_with_nll_infer_vars<T>(
877 &self,
878 all_outlive_scope: LocalDefId,
879 value: ty::Binder<'tcx, T>,
880 indices: &UniversalRegionIndices<'tcx>,
881 ) -> T
882 where
883 T: TypeFoldable<TyCtxt<'tcx>>,
884 {
885 let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
886 debug!(?br);
887 let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
888 let liberated_region =
889 ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
890 ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region))
891 });
892 value
893 }
894}
895
896impl<'tcx> UniversalRegionIndices<'tcx> {
897 fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
903 debug!("insert_late_bound_region({:?}, {:?})", r, vid);
904 assert_eq!(self.indices.insert(r, vid), None);
905 }
906
907 fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
920 match r.kind() {
921 ty::ReVar(..) => r.as_var(),
922 ty::ReError(guar) => {
923 self.encountered_re_error.set(Some(guar));
924 self.fr_static
928 }
929 _ => *self
930 .indices
931 .get(&r)
932 .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)),
933 }
934 }
935
936 fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
939 where
940 T: TypeFoldable<TyCtxt<'tcx>>,
941 {
942 fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
943 }
944}
945
946fn for_each_late_bound_region_in_recursive_scope<'tcx>(
950 tcx: TyCtxt<'tcx>,
951 mut mir_def_id: LocalDefId,
952 mut f: impl FnMut(ty::Region<'tcx>),
953) {
954 let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
955
956 loop {
958 for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
959
960 if mir_def_id.to_def_id() == typeck_root_def_id {
961 break;
962 } else {
963 mir_def_id = tcx.local_parent(mir_def_id);
964 }
965 }
966}
967
968fn for_each_late_bound_region_in_item<'tcx>(
972 tcx: TyCtxt<'tcx>,
973 mir_def_id: LocalDefId,
974 mut f: impl FnMut(ty::Region<'tcx>),
975) {
976 let bound_vars = match tcx.def_kind(mir_def_id) {
977 DefKind::Fn | DefKind::AssocFn => {
978 tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id))
979 }
980 DefKind::Closure => {
984 let ty = tcx.type_of(mir_def_id).instantiate_identity();
985 match *ty.kind() {
986 ty::Closure(_, args) => args.as_closure().sig().bound_vars(),
987 ty::CoroutineClosure(_, args) => {
988 args.as_coroutine_closure().coroutine_closure_sig().bound_vars()
989 }
990 ty::Coroutine(_, _) | ty::Error(_) => return,
991 _ => unreachable!("unexpected type for closure: {ty}"),
992 }
993 }
994 _ => return,
995 };
996
997 for (idx, bound_var) in bound_vars.iter().enumerate() {
998 if let ty::BoundVariableKind::Region(kind) = bound_var {
999 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
1000 let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
1001 f(liberated_region);
1002 }
1003 }
1004}