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::DefKind;
25use rustc_hir::def_id::{DefId, LocalDefId};
26use rustc_hir::lang_items::LangItem;
27use rustc_index::IndexVec;
28use rustc_infer::infer::NllRegionVariableOrigin;
29use rustc_macros::extension;
30use rustc_middle::ty::print::with_no_trimmed_paths;
31use rustc_middle::ty::{
32 self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
33 TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
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)]
43#[derive(Clone)] pub(crate) struct UniversalRegions<'tcx> {
45 indices: UniversalRegionIndices<'tcx>,
46
47 pub fr_static: RegionVid,
49
50 pub fr_fn_body: RegionVid,
54
55 first_extern_index: usize,
62
63 first_local_index: usize,
65
66 num_universals: usize,
68
69 pub defining_ty: DefiningTy<'tcx>,
73
74 pub unnormalized_output_ty: Ty<'tcx>,
80
81 pub unnormalized_input_tys: &'tcx [Ty<'tcx>],
87
88 pub yield_ty: Option<Ty<'tcx>>,
89
90 pub resume_ty: Option<Ty<'tcx>>,
91}
92
93#[derive(Copy, Clone, Debug)]
100pub(crate) enum DefiningTy<'tcx> {
101 Closure(DefId, GenericArgsRef<'tcx>),
104
105 Coroutine(DefId, GenericArgsRef<'tcx>),
109
110 CoroutineClosure(DefId, GenericArgsRef<'tcx>),
116
117 FnDef(DefId, GenericArgsRef<'tcx>),
120
121 Const(DefId, GenericArgsRef<'tcx>),
125
126 InlineConst(DefId, GenericArgsRef<'tcx>),
129
130 GlobalAsm(DefId),
134}
135
136impl<'tcx> DefiningTy<'tcx> {
137 pub(crate) fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> {
142 match self {
143 DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
144 DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
145 DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
146 DefiningTy::FnDef(..)
147 | DefiningTy::Const(..)
148 | DefiningTy::InlineConst(..)
149 | DefiningTy::GlobalAsm(_) => ty::List::empty(),
150 }
151 }
152
153 pub(crate) fn implicit_inputs(self) -> usize {
157 match self {
158 DefiningTy::Closure(..)
159 | DefiningTy::CoroutineClosure(..)
160 | DefiningTy::Coroutine(..) => 1,
161 DefiningTy::FnDef(..)
162 | DefiningTy::Const(..)
163 | DefiningTy::InlineConst(..)
164 | DefiningTy::GlobalAsm(_) => 0,
165 }
166 }
167
168 pub(crate) fn is_fn_def(&self) -> bool {
169 matches!(*self, DefiningTy::FnDef(..))
170 }
171
172 pub(crate) fn is_const(&self) -> bool {
173 matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
174 }
175
176 pub(crate) fn def_id(&self) -> DefId {
177 match *self {
178 DefiningTy::Closure(def_id, ..)
179 | DefiningTy::CoroutineClosure(def_id, ..)
180 | DefiningTy::Coroutine(def_id, ..)
181 | DefiningTy::FnDef(def_id, ..)
182 | DefiningTy::Const(def_id, ..)
183 | DefiningTy::InlineConst(def_id, ..)
184 | DefiningTy::GlobalAsm(def_id) => def_id,
185 }
186 }
187
188 pub(crate) fn args(&self) -> ty::GenericArgsRef<'tcx> {
191 match *self {
192 DefiningTy::Closure(_, args)
193 | DefiningTy::Coroutine(_, args)
194 | DefiningTy::CoroutineClosure(_, args)
195 | DefiningTy::FnDef(_, args)
196 | DefiningTy::Const(_, args)
197 | DefiningTy::InlineConst(_, args) => args,
198 DefiningTy::GlobalAsm(_) => ty::List::empty(),
199 }
200 }
201}
202
203#[derive(Debug)]
204#[derive(Clone)] struct UniversalRegionIndices<'tcx> {
206 indices: FxIndexMap<ty::Region<'tcx>, RegionVid>,
216
217 pub fr_static: RegionVid,
219
220 pub encountered_re_error: Cell<Option<ErrorGuaranteed>>,
223}
224
225#[derive(Debug, PartialEq)]
226pub(crate) enum RegionClassification {
227 Global,
230
231 External,
253
254 Local,
266}
267
268const FIRST_GLOBAL_INDEX: usize = 0;
269
270impl<'tcx> UniversalRegions<'tcx> {
271 pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
277 UniversalRegionsBuilder { infcx, mir_def }.build()
278 }
279
280 pub(crate) fn closure_mapping(
290 tcx: TyCtxt<'tcx>,
291 closure_args: GenericArgsRef<'tcx>,
292 expected_num_vars: usize,
293 closure_def_id: LocalDefId,
294 ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
295 let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
296 region_mapping.push(tcx.lifetimes.re_static);
297 tcx.for_each_free_region(&closure_args, |fr| {
298 region_mapping.push(fr);
299 });
300
301 for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
302 region_mapping.push(r);
303 });
304
305 assert_eq!(
306 region_mapping.len(),
307 expected_num_vars,
308 "index vec had unexpected number of variables"
309 );
310
311 region_mapping
312 }
313
314 pub(crate) fn is_universal_region(&self, r: RegionVid) -> bool {
316 (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index())
317 }
318
319 pub(crate) fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> {
322 let index = r.index();
323 if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) {
324 Some(RegionClassification::Global)
325 } else if (self.first_extern_index..self.first_local_index).contains(&index) {
326 Some(RegionClassification::External)
327 } else if (self.first_local_index..self.num_universals).contains(&index) {
328 Some(RegionClassification::Local)
329 } else {
330 None
331 }
332 }
333
334 pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> + 'static {
337 (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
338 }
339
340 pub(crate) fn is_local_free_region(&self, r: RegionVid) -> bool {
342 self.region_classification(r) == Some(RegionClassification::Local)
343 }
344
345 pub(crate) fn len(&self) -> usize {
347 self.num_universals
348 }
349
350 pub(crate) fn num_global_and_external_regions(&self) -> usize {
356 self.first_local_index
357 }
358
359 pub(crate) fn named_universal_regions_iter(
361 &self,
362 ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> {
363 self.indices.indices.iter().map(|(&r, &v)| (r, v))
364 }
365
366 pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
368 self.indices.to_region_vid(r)
369 }
370
371 pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
378 match self.defining_ty {
379 DefiningTy::Closure(def_id, args) => {
380 let v = with_no_trimmed_paths!(
381 args[tcx.generics_of(def_id).parent_count..]
382 .iter()
383 .map(|arg| arg.to_string())
384 .collect::<Vec<_>>()
385 );
386 err.note(format!(
387 "defining type: {} with closure args [\n {},\n]",
388 tcx.def_path_str_with_args(def_id, args),
389 v.join(",\n "),
390 ));
391
392 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
398 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
399 });
400 }
401 DefiningTy::CoroutineClosure(..) => {
402 todo!()
403 }
404 DefiningTy::Coroutine(def_id, args) => {
405 let v = with_no_trimmed_paths!(
406 args[tcx.generics_of(def_id).parent_count..]
407 .iter()
408 .map(|arg| arg.to_string())
409 .collect::<Vec<_>>()
410 );
411 err.note(format!(
412 "defining type: {} with coroutine args [\n {},\n]",
413 tcx.def_path_str_with_args(def_id, args),
414 v.join(",\n "),
415 ));
416
417 for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
421 err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
422 });
423 }
424 DefiningTy::FnDef(def_id, args) => {
425 err.note(format!("defining type: {}", tcx.def_path_str_with_args(def_id, args),));
426 }
427 DefiningTy::Const(def_id, args) => {
428 err.note(format!(
429 "defining constant type: {}",
430 tcx.def_path_str_with_args(def_id, args),
431 ));
432 }
433 DefiningTy::InlineConst(def_id, args) => {
434 err.note(format!(
435 "defining inline constant type: {}",
436 tcx.def_path_str_with_args(def_id, args),
437 ));
438 }
439 DefiningTy::GlobalAsm(_) => unreachable!(),
440 }
441 }
442
443 pub(crate) fn implicit_region_bound(&self) -> RegionVid {
444 self.fr_fn_body
445 }
446
447 pub(crate) fn encountered_re_error(&self) -> Option<ErrorGuaranteed> {
448 self.indices.encountered_re_error.get()
449 }
450}
451
452struct UniversalRegionsBuilder<'infcx, 'tcx> {
453 infcx: &'infcx BorrowckInferCtxt<'tcx>,
454 mir_def: LocalDefId,
455}
456
457const FR: NllRegionVariableOrigin = NllRegionVariableOrigin::FreeRegion;
458
459impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
460 fn build(self) -> UniversalRegions<'tcx> {
461 debug!("build(mir_def={:?})", self.mir_def);
462
463 let param_env = self.infcx.param_env;
464 debug!("build: param_env={:?}", param_env);
465
466 assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
467
468 let fr_static =
470 self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).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(FR, || RegionCtxt::LateBound(name))
504 };
505
506 debug!(?region_vid);
507 indices.insert_late_bound_region(r, region_vid.as_var());
508 },
509 );
510
511 self.infcx.num_region_vars()
514 };
515
516 let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
523 for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
524 if let ty::BoundVariableKind::Region(kind) = bound_var {
525 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
526 let r = ty::Region::new_late_param(self.infcx.tcx, self.mir_def.to_def_id(), kind);
527 let region_vid = {
528 let name = r.get_name_or_anon(self.infcx.tcx);
529 self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
530 };
531
532 debug!(?region_vid);
533 indices.insert_late_bound_region(r, region_vid.as_var());
534 }
535 }
536 let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
537 self.mir_def,
538 bound_inputs_and_output,
539 &indices,
540 );
541
542 let (unnormalized_output_ty, mut unnormalized_input_tys) =
543 inputs_and_output.split_last().unwrap();
544
545 if let DefiningTy::FnDef(def_id, _) = defining_ty {
548 if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
549 let va_list_did = self
550 .infcx
551 .tcx
552 .require_lang_item(LangItem::VaList, self.infcx.tcx.def_span(self.mir_def));
553
554 let reg_vid = self
555 .infcx
556 .next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic))
557 .as_var();
558
559 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
560 let va_list_ty = self
561 .infcx
562 .tcx
563 .type_of(va_list_did)
564 .instantiate(self.infcx.tcx, &[region.into()]);
565
566 unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter(
567 unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
568 );
569 }
570 }
571
572 let fr_fn_body =
573 self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var();
574
575 let num_universals = self.infcx.num_region_vars();
576
577 debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index);
578 debug!("build: extern regions = {}..{}", first_extern_index, first_local_index);
579 debug!("build: local regions = {}..{}", first_local_index, num_universals);
580
581 let (resume_ty, yield_ty) = match defining_ty {
582 DefiningTy::Coroutine(_, args) => {
583 let tys = args.as_coroutine();
584 (Some(tys.resume_ty()), Some(tys.yield_ty()))
585 }
586 _ => (None, None),
587 };
588
589 UniversalRegions {
590 indices,
591 fr_static,
592 fr_fn_body,
593 first_extern_index,
594 first_local_index,
595 num_universals,
596 defining_ty,
597 unnormalized_output_ty: *unnormalized_output_ty,
598 unnormalized_input_tys,
599 yield_ty,
600 resume_ty,
601 }
602 }
603
604 fn defining_ty(&self) -> DefiningTy<'tcx> {
607 let tcx = self.infcx.tcx;
608 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
609
610 match tcx.hir_body_owner_kind(self.mir_def) {
611 BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
612 let defining_ty = tcx.type_of(self.mir_def).instantiate_identity();
613
614 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
615
616 let defining_ty =
617 self.infcx.replace_free_regions_with_nll_infer_vars(FR, defining_ty);
618
619 match *defining_ty.kind() {
620 ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args),
621 ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args),
622 ty::CoroutineClosure(def_id, args) => {
623 DefiningTy::CoroutineClosure(def_id, args)
624 }
625 ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args),
626 _ => span_bug!(
627 tcx.def_span(self.mir_def),
628 "expected defining type for `{:?}`: `{:?}`",
629 self.mir_def,
630 defining_ty
631 ),
632 }
633 }
634
635 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => {
636 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
637 if self.mir_def.to_def_id() == typeck_root_def_id
638 && DefKind::Field != tcx.def_kind(tcx.parent(typeck_root_def_id))
640 {
641 let args =
642 self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
643 DefiningTy::Const(self.mir_def.to_def_id(), args)
644 } else {
645 let ty = tcx
655 .typeck(self.mir_def)
656 .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
657 let args = InlineConstArgs::new(
658 tcx,
659 InlineConstArgsParts { parent_args: identity_args, ty },
660 )
661 .args;
662 let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, args);
663 DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
664 }
665 }
666
667 BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
668 }
669 }
670
671 fn compute_indices(
676 &self,
677 fr_static: RegionVid,
678 defining_ty: DefiningTy<'tcx>,
679 ) -> UniversalRegionIndices<'tcx> {
680 let tcx = self.infcx.tcx;
681 let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
682 let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
683 let fr_args = match defining_ty {
684 DefiningTy::Closure(_, args)
685 | DefiningTy::CoroutineClosure(_, args)
686 | DefiningTy::Coroutine(_, args)
687 | DefiningTy::InlineConst(_, args) => {
688 assert!(args.len() >= identity_args.len());
696 assert_eq!(args.regions().count(), identity_args.regions().count());
697 args
698 }
699
700 DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
701
702 DefiningTy::GlobalAsm(_) => ty::List::empty(),
703 };
704
705 let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
706 let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
707
708 UniversalRegionIndices {
709 indices: global_mapping.chain(arg_mapping).collect(),
710 fr_static,
711 encountered_re_error: Cell::new(None),
712 }
713 }
714
715 fn compute_inputs_and_output(
716 &self,
717 indices: &UniversalRegionIndices<'tcx>,
718 defining_ty: DefiningTy<'tcx>,
719 ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
720 let tcx = self.infcx.tcx;
721
722 let inputs_and_output = match defining_ty {
723 DefiningTy::Closure(def_id, args) => {
724 assert_eq!(self.mir_def.to_def_id(), def_id);
725 let closure_sig = args.as_closure().sig();
726 let inputs_and_output = closure_sig.inputs_and_output();
727 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
728 inputs_and_output.bound_vars().iter().chain(iter::once(
729 ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
730 )),
731 );
732 let br = ty::BoundRegion {
733 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
734 kind: ty::BoundRegionKind::ClosureEnv,
735 };
736 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
737 let closure_ty = tcx.closure_env_ty(
738 Ty::new_closure(tcx, def_id, args),
739 args.as_closure().kind(),
740 env_region,
741 );
742
743 let (&output, tuplized_inputs) =
747 inputs_and_output.skip_binder().split_last().unwrap();
748 assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
749 let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else {
750 bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]);
751 };
752
753 ty::Binder::bind_with_vars(
754 tcx.mk_type_list_from_iter(
755 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
756 ),
757 bound_vars,
758 )
759 }
760
761 DefiningTy::Coroutine(def_id, args) => {
762 assert_eq!(self.mir_def.to_def_id(), def_id);
763 let resume_ty = args.as_coroutine().resume_ty();
764 let output = args.as_coroutine().return_ty();
765 let coroutine_ty = Ty::new_coroutine(tcx, def_id, args);
766 let inputs_and_output =
767 self.infcx.tcx.mk_type_list(&[coroutine_ty, resume_ty, output]);
768 ty::Binder::dummy(inputs_and_output)
769 }
770
771 DefiningTy::CoroutineClosure(def_id, args) => {
780 assert_eq!(self.mir_def.to_def_id(), def_id);
781 let closure_sig = args.as_coroutine_closure().coroutine_closure_sig();
782 let bound_vars =
783 tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain(
784 iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)),
785 ));
786 let br = ty::BoundRegion {
787 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
788 kind: ty::BoundRegionKind::ClosureEnv,
789 };
790 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
791 let closure_kind = args.as_coroutine_closure().kind();
792
793 let closure_ty = tcx.closure_env_ty(
794 Ty::new_coroutine_closure(tcx, def_id, args),
795 closure_kind,
796 env_region,
797 );
798
799 let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields();
800 let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars(
801 tcx,
802 args.as_coroutine_closure().parent_args(),
803 tcx.coroutine_for_closure(def_id),
804 closure_kind,
805 env_region,
806 args.as_coroutine_closure().tupled_upvars_ty(),
807 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
808 );
809
810 ty::Binder::bind_with_vars(
811 tcx.mk_type_list_from_iter(
812 iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
813 ),
814 bound_vars,
815 )
816 }
817
818 DefiningTy::FnDef(def_id, _) => {
819 let sig = tcx.fn_sig(def_id).instantiate_identity();
820 let sig = indices.fold_to_region_vids(tcx, sig);
821 sig.inputs_and_output()
822 }
823
824 DefiningTy::Const(def_id, _) => {
825 assert_eq!(self.mir_def.to_def_id(), def_id);
828 let ty = tcx.type_of(self.mir_def).instantiate_identity();
829
830 let ty = indices.fold_to_region_vids(tcx, ty);
831 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
832 }
833
834 DefiningTy::InlineConst(def_id, args) => {
835 assert_eq!(self.mir_def.to_def_id(), def_id);
836 let ty = args.as_inline_const().ty();
837 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
838 }
839
840 DefiningTy::GlobalAsm(def_id) => {
841 ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
842 }
843 };
844
845 if let Err(terr) = inputs_and_output.skip_binder().error_reported() {
847 self.infcx.set_tainted_by_errors(terr);
848 }
849
850 inputs_and_output
851 }
852}
853
854#[extension(trait InferCtxtExt<'tcx>)]
855impl<'tcx> BorrowckInferCtxt<'tcx> {
856 #[instrument(skip(self), level = "debug")]
857 fn replace_free_regions_with_nll_infer_vars<T>(
858 &self,
859 origin: NllRegionVariableOrigin,
860 value: T,
861 ) -> T
862 where
863 T: TypeFoldable<TyCtxt<'tcx>>,
864 {
865 fold_regions(self.infcx.tcx, value, |region, _depth| {
866 let name = region.get_name_or_anon(self.infcx.tcx);
867 debug!(?region, ?name);
868
869 self.next_nll_region_var(origin, || RegionCtxt::Free(name))
870 })
871 }
872
873 #[instrument(level = "debug", skip(self, indices))]
874 fn replace_bound_regions_with_nll_infer_vars<T>(
875 &self,
876 all_outlive_scope: LocalDefId,
877 value: ty::Binder<'tcx, T>,
878 indices: &UniversalRegionIndices<'tcx>,
879 ) -> T
880 where
881 T: TypeFoldable<TyCtxt<'tcx>>,
882 {
883 let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| {
884 debug!(?br);
885 let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
886 let liberated_region =
887 ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
888 ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region))
889 });
890 value
891 }
892}
893
894impl<'tcx> UniversalRegionIndices<'tcx> {
895 fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
901 debug!("insert_late_bound_region({:?}, {:?})", r, vid);
902 assert_eq!(self.indices.insert(r, vid), None);
903 }
904
905 fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
918 match r.kind() {
919 ty::ReVar(..) => r.as_var(),
920 ty::ReError(guar) => {
921 self.encountered_re_error.set(Some(guar));
922 self.fr_static
926 }
927 _ => *self
928 .indices
929 .get(&r)
930 .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)),
931 }
932 }
933
934 fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
937 where
938 T: TypeFoldable<TyCtxt<'tcx>>,
939 {
940 fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
941 }
942}
943
944fn for_each_late_bound_region_in_recursive_scope<'tcx>(
948 tcx: TyCtxt<'tcx>,
949 mut mir_def_id: LocalDefId,
950 mut f: impl FnMut(ty::Region<'tcx>),
951) {
952 let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
953
954 loop {
956 for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
957
958 if mir_def_id.to_def_id() == typeck_root_def_id {
959 break;
960 } else {
961 mir_def_id = tcx.local_parent(mir_def_id);
962 }
963 }
964}
965
966fn for_each_late_bound_region_in_item<'tcx>(
970 tcx: TyCtxt<'tcx>,
971 mir_def_id: LocalDefId,
972 mut f: impl FnMut(ty::Region<'tcx>),
973) {
974 let bound_vars = match tcx.def_kind(mir_def_id) {
975 DefKind::Fn | DefKind::AssocFn => {
976 tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id))
977 }
978 DefKind::Closure => {
982 let ty = tcx.type_of(mir_def_id).instantiate_identity();
983 match *ty.kind() {
984 ty::Closure(_, args) => args.as_closure().sig().bound_vars(),
985 ty::CoroutineClosure(_, args) => {
986 args.as_coroutine_closure().coroutine_closure_sig().bound_vars()
987 }
988 ty::Coroutine(_, _) | ty::Error(_) => return,
989 _ => unreachable!("unexpected type for closure: {ty}"),
990 }
991 }
992 _ => return,
993 };
994
995 for (idx, bound_var) in bound_vars.iter().enumerate() {
996 if let ty::BoundVariableKind::Region(kind) = bound_var {
997 let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
998 let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
999 f(liberated_region);
1000 }
1001 }
1002}