1#![allow(rustc::diagnostic_outside_of_impl)]
16#![allow(rustc::untranslatable_diagnostic)]
17
18use std::cell::Cell;
19use std::iter;
20
21use rustc_data_structures::fx::FxIndexMap;
22use rustc_errors::Diag;
23use rustc_hir::BodyOwnerKind;
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::fold::{TypeFoldable, fold_regions};
30use rustc_middle::ty::print::with_no_trimmed_paths;
31use rustc_middle::ty::{
32 self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
33 TyCtxt, TypeVisitableExt,
34};
35use rustc_middle::{bug, span_bug};
36use rustc_span::{ErrorGuaranteed, kw, sym};
37use tracing::{debug, instrument};
38
39use crate::BorrowckInferCtxt;
40use crate::renumber::RegionCtxt;
41
42#[derive(Debug)]
43pub(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
130impl<'tcx> DefiningTy<'tcx> {
131 pub(crate) fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
136 match self {
137 DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
138 DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
139 DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
140 DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
141 ty::List::empty()
142 }
143 }
144 }
145
146 pub(crate) fn implicit_inputs(self) -> usize {
150 match self {
151 DefiningTy::Closure(..)
152 | DefiningTy::CoroutineClosure(..)
153 | DefiningTy::Coroutine(..) => 1,
154 DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
155 }
156 }
157
158 pub(crate) fn is_fn_def(&self) -> bool {
159 matches!(*self, DefiningTy::FnDef(..))
160 }
161
162 pub(crate) fn is_const(&self) -> bool {
163 matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
164 }
165
166 pub(crate) fn def_id(&self) -> DefId {
167 match *self {
168 DefiningTy::Closure(def_id, ..)
169 | DefiningTy::CoroutineClosure(def_id, ..)
170 | DefiningTy::Coroutine(def_id, ..)
171 | DefiningTy::FnDef(def_id, ..)
172 | DefiningTy::Const(def_id, ..)
173 | DefiningTy::InlineConst(def_id, ..) => def_id,
174 }
175 }
176}
177
178#[derive(Debug)]
179struct UniversalRegionIndices<'tcx> {
180 indices: FxIndexMap<ty::Region<'tcx>, RegionVid>,
190
191 pub fr_static: RegionVid,
193
194 pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
197}
198
199#[derive(Debug, PartialEq)]
200pub(crate) enum RegionClassification {
201 Global,
204
205 External,
227
228 Local,
240}
241
242const FIRST_GLOBAL_INDEX: usize = 0;
243
244impl<'tcx> UniversalRegions<'tcx> {
245 pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
251 UniversalRegionsBuilder { infcx, mir_def }.build()
252 }
253
254 pub(crate) fn closure_mapping(
264 tcx: TyCtxt<'tcx>,
265 closure_args: GenericArgsRef<'tcx>,
266 expected_num_vars: usize,
267 closure_def_id: LocalDefId,
268 ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
269 let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
270 region_mapping.push(tcx.lifetimes.re_static);
271 tcx.for_each_free_region(&closure_args, |fr| {
272 region_mapping.push(fr);
273 });
274
275 for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
276 region_mapping.push(r);
277 });
278
279 assert_eq!(
280 region_mapping.len(),
281 expected_num_vars,
282 "index vec had unexpected number of variables"
283 );
284
285 region_mapping
286 }
287
288 pub(crate) fn is_universal_region(&self, r: RegionVid) -> bool {
290 (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index())
291 }
292
293 pub(crate) fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> {
296 let index = r.index();
297 if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) {
298 Some(RegionClassification::Global)
299 } else if (self.first_extern_index..self.first_local_index).contains(&index) {
300 Some(RegionClassification::External)
301 } else if (self.first_local_index..self.num_universals).contains(&index) {
302 Some(RegionClassification::Local)
303 } else {
304 None
305 }
306 }
307
308 pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> {
311 (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
312 }
313
314 pub(crate) fn is_local_free_region(&self, r: RegionVid) -> bool {
316 self.region_classification(r) == Some(RegionClassification::Local)
317 }
318
319 pub(crate) fn len(&self) -> usize {
321 self.num_universals
322 }
323
324 pub(crate) fn num_global_and_external_regions(&self) -> usize {
330 self.first_local_index
331 }
332
333 pub(crate) fn named_universal_regions_iter<'s>(
335 &'s self,
336 ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
337 self.indices.indices.iter().map(|(&r, &v)| (r, v))
338 }
339
340 pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
342 self.indices.to_region_vid(r)
343 }
344
345 pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
352 match self.defining_ty {
353 DefiningTy::Closure(def_id, args) => {
354 let v = with_no_trimmed_paths!(
355 args[tcx.generics_of(def_id).parent_count..]
356 .iter()
357 .map(|arg| arg.to_string())
358 .collect::<Vec<_>>()
359 );
360 err.note(format!(
361 "defining type: {} with closure args [\n {},\n]",
362 tcx.def_path_str_with_args(def_id, args),
363 v.join(",\n "),
364 ));
365
366 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
372 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
373 });
374 }
375 DefiningTy::CoroutineClosure(..) => {
376 todo!()
377 }
378 DefiningTy::Coroutine(def_id, args) => {
379 let v = with_no_trimmed_paths!(
380 args[tcx.generics_of(def_id).parent_count..]
381 .iter()
382 .map(|arg| arg.to_string())
383 .collect::<Vec<_>>()
384 );
385 err.note(format!(
386 "defining type: {} with coroutine args [\n {},\n]",
387 tcx.def_path_str_with_args(def_id, args),
388 v.join(",\n "),
389 ));
390
391 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
395 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
396 });
397 }
398 DefiningTy::FnDef(def_id, args) => {
399 err.note(format!("defining type: {}", tcx.def_path_str_with_args(def_id, args),));
400 }
401 DefiningTy::Const(def_id, args) => {
402 err.note(format!(
403 "defining constant type: {}",
404 tcx.def_path_str_with_args(def_id, args),
405 ));
406 }
407 DefiningTy::InlineConst(def_id, args) => {
408 err.note(format!(
409 "defining inline constant type: {}",
410 tcx.def_path_str_with_args(def_id, args),
411 ));
412 }
413 }
414 }
415
416 pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
417 self.indices.tainted_by_errors.get()
418 }
419}
420
421struct UniversalRegionsBuilder<'infcx, 'tcx> {
422 infcx: &'infcx BorrowckInferCtxt<'tcx>,
423 mir_def: LocalDefId,
424}
425
426const FR: NllRegionVariableOrigin = NllRegionVariableOrigin::FreeRegion;
427
428impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
429 fn build(self) -> UniversalRegions<'tcx> {
430 debug!("build(mir_def={:?})", self.mir_def);
431
432 let param_env = self.infcx.param_env;
433 debug!("build: param_env={:?}", param_env);
434
435 assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
436
437 let fr_static =
439 self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).as_var();
440
441 let first_extern_index = self.infcx.num_region_vars();
444
445 let defining_ty = self.defining_ty();
446 debug!("build: defining_ty={:?}", defining_ty);
447
448 let mut indices = self.compute_indices(fr_static, defining_ty);
449 debug!("build: indices={:?}", indices);
450
451 let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
452
453 let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
457 first_extern_index
458 } else {
459 for_each_late_bound_region_in_recursive_scope(
466 self.infcx.tcx,
467 self.infcx.tcx.local_parent(self.mir_def),
468 |r| {
469 debug!(?r);
470 let region_vid = {
471 let name = r.get_name_or_anon();
472 self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
473 };
474
475 debug!(?region_vid);
476 indices.insert_late_bound_region(r, region_vid.as_var());
477 },
478 );
479
480 self.infcx.num_region_vars()
483 };
484
485 let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
492 for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
493 if let ty::BoundVariableKind::Region(kind) = bound_var {
494 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
495 let r = ty::Region::new_late_param(self.infcx.tcx, self.mir_def.to_def_id(), kind);
496 let region_vid = {
497 let name = r.get_name_or_anon();
498 self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
499 };
500
501 debug!(?region_vid);
502 indices.insert_late_bound_region(r, region_vid.as_var());
503 }
504 }
505 let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
506 self.mir_def,
507 bound_inputs_and_output,
508 &indices,
509 );
510
511 let (unnormalized_output_ty, mut unnormalized_input_tys) =
512 inputs_and_output.split_last().unwrap();
513
514 if let DefiningTy::FnDef(def_id, _) = defining_ty {
517 if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
518 let va_list_did = self.infcx.tcx.require_lang_item(
519 LangItem::VaList,
520 Some(self.infcx.tcx.def_span(self.mir_def)),
521 );
522
523 let reg_vid = self
524 .infcx
525 .next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic))
526 .as_var();
527
528 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
529 let va_list_ty = self
530 .infcx
531 .tcx
532 .type_of(va_list_did)
533 .instantiate(self.infcx.tcx, &[region.into()]);
534
535 unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter(
536 unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
537 );
538 }
539 }
540
541 let fr_fn_body =
542 self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var();
543
544 let num_universals = self.infcx.num_region_vars();
545
546 debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index);
547 debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
548 debug!("build: local regions = {}..{}", first_local_index, num_universals);
549
550 let (resume_ty, yield_ty) = match defining_ty {
551 DefiningTy::Coroutine(_, args) => {
552 let tys = args.as_coroutine();
553 (Some(tys.resume_ty()), Some(tys.yield_ty()))
554 }
555 _ => (None, None),
556 };
557
558 UniversalRegions {
559 indices,
560 fr_static,
561 fr_fn_body,
562 first_extern_index,
563 first_local_index,
564 num_universals,
565 defining_ty,
566 unnormalized_output_ty: *unnormalized_output_ty,
567 unnormalized_input_tys,
568 yield_ty,
569 resume_ty,
570 }
571 }
572
573 fn defining_ty(&self) -> DefiningTy<'tcx> {
576 let tcx = self.infcx.tcx;
577 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
578
579 match tcx.hir().body_owner_kind(self.mir_def) {
580 BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
581 let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
582
583 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
584
585 let defining_ty =
586 self.infcx.replace_free_regions_with_nll_infer_vars(FR, defining_ty);
587
588 match *defining_ty.kind() {
589 ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
590 ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args),
591 ty::CoroutineClosure(def_id, args) => {
592 DefiningTy::CoroutineClosure(def_id, args)
593 }
594 ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
595 _ => span_bug!(
596 tcx.def_span(self.mir_def),
597 "expected defining type for `{:?}`: `{:?}`",
598 self.mir_def,
599 defining_ty
600 ),
601 }
602 }
603
604 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
605 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
606 if self.mir_def.to_def_id() == typeck_root_def_id {
607 let args =
608 self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
609 DefiningTy::Const(self.mir_def.to_def_id(), args)
610 } else {
611 let ty = tcx
621 .typeck(self.mir_def)
622 .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
623 let args = InlineConstArgs::new(
624 tcx,
625 InlineConstArgsParts { parent_args: identity_args, ty },
626 )
627 .args;
628 let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, args);
629 DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
630 }
631 }
632 }
633 }
634
635 fn compute_indices(
640 &self,
641 fr_static: RegionVid,
642 defining_ty: DefiningTy<'tcx>,
643 ) -> UniversalRegionIndices<'tcx> {
644 let tcx = self.infcx.tcx;
645 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
646 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
647 let fr_args = match defining_ty {
648 DefiningTy::Closure(_, args)
649 | DefiningTy::CoroutineClosure(_, args)
650 | DefiningTy::Coroutine(_, args)
651 | DefiningTy::InlineConst(_, args) => {
652 assert!(args.len() >= identity_args.len());
660 assert_eq!(args.regions().count(), identity_args.regions().count());
661 args
662 }
663
664 DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
665 };
666
667 let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
668 let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
669
670 UniversalRegionIndices {
671 indices: global_mapping.chain(arg_mapping).collect(),
672 fr_static,
673 tainted_by_errors: Cell::new(None),
674 }
675 }
676
677 fn compute_inputs_and_output(
678 &self,
679 indices: &UniversalRegionIndices<'tcx>,
680 defining_ty: DefiningTy<'tcx>,
681 ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
682 let tcx = self.infcx.tcx;
683
684 let inputs_and_output = match defining_ty {
685 DefiningTy::Closure(def_id, args) => {
686 assert_eq!(self.mir_def.to_def_id(), def_id);
687 let closure_sig = args.as_closure().sig();
688 let inputs_and_output = closure_sig.inputs_and_output();
689 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
690 inputs_and_output.bound_vars().iter().chain(iter::once(
691 ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
692 )),
693 );
694 let br = ty::BoundRegion {
695 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
696 kind: ty::BoundRegionKind::ClosureEnv,
697 };
698 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
699 let closure_ty = tcx.closure_env_ty(
700 Ty::new_closure(tcx, def_id, args),
701 args.as_closure().kind(),
702 env_region,
703 );
704
705 let (&output, tuplized_inputs) =
709 inputs_and_output.skip_binder().split_last().unwrap();
710 assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
711 let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else {
712 bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]);
713 };
714
715 ty::Binder::bind_with_vars(
716 tcx.mk_type_list_from_iter(
717 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
718 ),
719 bound_vars,
720 )
721 }
722
723 DefiningTy::Coroutine(def_id, args) => {
724 assert_eq!(self.mir_def.to_def_id(), def_id);
725 let resume_ty = args.as_coroutine().resume_ty();
726 let output = args.as_coroutine().return_ty();
727 let coroutine_ty = Ty::new_coroutine(tcx, def_id, args);
728 let inputs_and_output =
729 self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
730 ty::Binder::dummy(inputs_and_output)
731 }
732
733 DefiningTy::CoroutineClosure(def_id, args) => {
742 assert_eq!(self.mir_def.to_def_id(), def_id);
743 let closure_sig = args.as_coroutine_closure().coroutine_closure_sig();
744 let bound_vars =
745 tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain(
746 iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)),
747 ));
748 let br = ty::BoundRegion {
749 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
750 kind: ty::BoundRegionKind::ClosureEnv,
751 };
752 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
753 let closure_kind = args.as_coroutine_closure().kind();
754
755 let closure_ty = tcx.closure_env_ty(
756 Ty::new_coroutine_closure(tcx, def_id, args),
757 closure_kind,
758 env_region,
759 );
760
761 let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields();
762 let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars(
763 tcx,
764 args.as_coroutine_closure().parent_args(),
765 tcx.coroutine_for_closure(def_id),
766 closure_kind,
767 env_region,
768 args.as_coroutine_closure().tupled_upvars_ty(),
769 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
770 );
771
772 ty::Binder::bind_with_vars(
773 tcx.mk_type_list_from_iter(
774 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
775 ),
776 bound_vars,
777 )
778 }
779
780 DefiningTy::FnDef(def_id, _) => {
781 let sig = tcx.fn_sig(def_id).instantiate_identity();
782 let sig = indices.fold_to_region_vids(tcx, sig);
783 sig.inputs_and_output()
784 }
785
786 DefiningTy::Const(def_id, _) => {
787 assert_eq!(self.mir_def.to_def_id(), def_id);
790 let ty = tcx.type_of(self.mir_def).instantiate_identity();
791
792 let ty = indices.fold_to_region_vids(tcx, ty);
793 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
794 }
795
796 DefiningTy::InlineConst(def_id, args) => {
797 assert_eq!(self.mir_def.to_def_id(), def_id);
798 let ty = args.as_inline_const().ty();
799 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
800 }
801 };
802
803 if let Err(terr) = inputs_and_output.skip_binder().error_reported() {
805 self.infcx.set_tainted_by_errors(terr);
806 }
807
808 inputs_and_output
809 }
810}
811
812#[extension(trait InferCtxtExt<'tcx>)]
813impl<'tcx> BorrowckInferCtxt<'tcx> {
814 #[instrument(skip(self), level = "debug")]
815 fn replace_free_regions_with_nll_infer_vars<T>(
816 &self,
817 origin: NllRegionVariableOrigin,
818 value: T,
819 ) -> T
820 where
821 T: TypeFoldable<TyCtxt<'tcx>>,
822 {
823 fold_regions(self.infcx.tcx, value, |region, _depth| {
824 let name = region.get_name_or_anon();
825 debug!(?region, ?name);
826
827 self.next_nll_region_var(origin, || RegionCtxt::Free(name))
828 })
829 }
830
831 #[instrument(level = "debug", skip(self, indices))]
832 fn replace_bound_regions_with_nll_infer_vars<T>(
833 &self,
834 all_outlive_scope: LocalDefId,
835 value: ty::Binder<'tcx, T>,
836 indices: &UniversalRegionIndices<'tcx>,
837 ) -> T
838 where
839 T: TypeFoldable<TyCtxt<'tcx>>,
840 {
841 let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
842 debug!(?br);
843 let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
844 let liberated_region =
845 ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
846 ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region))
847 });
848 value
849 }
850}
851
852impl<'tcx> UniversalRegionIndices<'tcx> {
853 fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
859 debug!("insert_late_bound_region({:?}, {:?})", r, vid);
860 assert_eq!(self.indices.insert(r, vid), None);
861 }
862
863 fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
876 if let ty::ReVar(..) = *r {
877 r.as_var()
878 } else if let ty::ReError(guar) = *r {
879 self.tainted_by_errors.set(Some(guar));
880 self.fr_static
884 } else {
885 *self
886 .indices
887 .get(&r)
888 .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r))
889 }
890 }
891
892 fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
895 where
896 T: TypeFoldable<TyCtxt<'tcx>>,
897 {
898 fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
899 }
900}
901
902fn for_each_late_bound_region_in_recursive_scope<'tcx>(
906 tcx: TyCtxt<'tcx>,
907 mut mir_def_id: LocalDefId,
908 mut f: impl FnMut(ty::Region<'tcx>),
909) {
910 let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
911
912 loop {
914 for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
915
916 if mir_def_id.to_def_id() == typeck_root_def_id {
917 break;
918 } else {
919 mir_def_id = tcx.local_parent(mir_def_id);
920 }
921 }
922}
923
924fn for_each_late_bound_region_in_item<'tcx>(
928 tcx: TyCtxt<'tcx>,
929 mir_def_id: LocalDefId,
930 mut f: impl FnMut(ty::Region<'tcx>),
931) {
932 if !tcx.def_kind(mir_def_id).is_fn_like() {
933 return;
934 }
935
936 for (idx, bound_var) in
937 tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate()
938 {
939 if let ty::BoundVariableKind::Region(kind) = bound_var {
940 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
941 let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
942 f(liberated_region);
943 }
944 }
945}