summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/universal_regions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/universal_regions.rs')
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs133
1 files changed, 96 insertions, 37 deletions
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 2beb5e0ab..a4a0c5b90 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,7 +22,9 @@ use rustc_hir::{BodyOwnerKind, HirId};
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{
+ self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt,
+};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use std::iter;
@@ -241,7 +243,7 @@ impl<'tcx> UniversalRegions<'tcx> {
tcx: TyCtxt<'tcx>,
closure_substs: SubstsRef<'tcx>,
expected_num_vars: usize,
- typeck_root_def_id: DefId,
+ closure_def_id: LocalDefId,
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
region_mapping.push(tcx.lifetimes.re_static);
@@ -249,7 +251,7 @@ impl<'tcx> UniversalRegions<'tcx> {
region_mapping.push(fr);
});
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
+ for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
region_mapping.push(r);
});
@@ -339,9 +341,8 @@ impl<'tcx> UniversalRegions<'tcx> {
// tests, and the resulting print-outs include def-ids
// and other things that are not stable across tests!
// So we just include the region-vid. Annoying.
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
- err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
+ for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
+ err.note(&format!("late-bound region is {:?}", self.to_region_vid(r)));
});
}
DefiningTy::Generator(def_id, substs, _) => {
@@ -354,9 +355,8 @@ impl<'tcx> UniversalRegions<'tcx> {
// FIXME: As above, we'd like to print out the region
// `r` but doing so is not stable across architectures
// and so forth.
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
- err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
+ for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
+ err.note(&format!("late-bound region is {:?}", self.to_region_vid(r)));
});
}
DefiningTy::FnDef(def_id, substs) => {
@@ -421,13 +421,24 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
first_extern_index
} else {
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
- // function are actually external regions to us. For example, here, 'a is not local
+ // function/closures are actually external regions to us. For example, here, 'a is not local
// to the closure c (although it is local to the fn foo):
// fn foo<'a>() {
// let c = || { let x: &'a u32 = ...; }
// }
- self.infcx
- .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
+ for_each_late_bound_region_in_recursive_scope(
+ self.infcx.tcx,
+ self.infcx.tcx.local_parent(self.mir_def.did),
+ |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.infcx.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ },
+ );
+
// Any regions created during the execution of `defining_ty` or during the above
// late-bound region replacement are all considered 'extern' regions
self.infcx.num_region_vars()
@@ -444,12 +455,16 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
bound_inputs_and_output,
&mut indices,
);
- // Converse of above, if this is a function then the late-bound regions declared on its
- // signature are local to the fn.
- if self.mir_def.did.to_def_id() == typeck_root_def_id {
- self.infcx
- .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
- }
+ // Converse of above, if this is a function/closure then the late-bound regions declared on its
+ // signature are local.
+ for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.infcx.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ });
let (unnormalized_output_ty, mut unnormalized_input_tys) =
inputs_and_output.split_last().unwrap();
@@ -572,9 +587,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
let fr_substs = match defining_ty {
- DefiningTy::Closure(_, ref substs)
- | DefiningTy::Generator(_, ref substs, _)
- | DefiningTy::InlineConst(_, ref substs) => {
+ DefiningTy::Closure(_, substs)
+ | DefiningTy::Generator(_, substs, _)
+ | DefiningTy::InlineConst(_, substs) => {
// In the case of closures, we rely on the fact that
// the first N elements in the ClosureSubsts are
// inherited from the `typeck_root_def_id`.
@@ -692,7 +707,13 @@ trait InferCtxtExt<'tcx> {
where
T: TypeFoldable<'tcx>;
- fn replace_late_bound_regions_with_nll_infer_vars(
+ fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
+ &self,
+ mir_def_id: LocalDefId,
+ indices: &mut UniversalRegionIndices<'tcx>,
+ );
+
+ fn replace_late_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
@@ -746,13 +767,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// set of late-bound regions and checks for any that we have not yet seen, adding them to the
/// inputs vector.
#[instrument(skip(self, indices))]
- fn replace_late_bound_regions_with_nll_infer_vars(
+ fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
+ &self,
+ mir_def_id: LocalDefId,
+ indices: &mut UniversalRegionIndices<'tcx>,
+ ) {
+ for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ });
+ }
+
+ #[instrument(skip(self, indices))]
+ fn replace_late_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
) {
- let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
- for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
+ for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
let region_vid = self.next_nll_region_var(FR);
@@ -803,21 +839,44 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
}
}
-/// Iterates over the late-bound regions defined on fn_def_id and
-/// invokes `f` with the liberated form of each one.
-fn for_each_late_bound_region_defined_on<'tcx>(
+/// Iterates over the late-bound regions defined on `mir_def_id` and all of its
+/// parents, up to the typeck root, and invokes `f` with the liberated form
+/// of each one.
+fn for_each_late_bound_region_in_recursive_scope<'tcx>(
tcx: TyCtxt<'tcx>,
- fn_def_id: DefId,
+ mut mir_def_id: LocalDefId,
mut f: impl FnMut(ty::Region<'tcx>),
) {
- if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
- for &region_def_id in late_bounds.iter() {
- let name = tcx.item_name(region_def_id.to_def_id());
- let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: fn_def_id,
- bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
- }));
- f(liberated_region);
+ let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
+
+ // Walk up the tree, collecting late-bound regions until we hit the typeck root
+ loop {
+ for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
+
+ if mir_def_id.to_def_id() == typeck_root_def_id {
+ break;
+ } else {
+ mir_def_id = tcx.local_parent(mir_def_id);
}
}
}
+
+/// Iterates over the late-bound regions defined on `mir_def_id` and all of its
+/// parents, up to the typeck root, and invokes `f` with the liberated form
+/// of each one.
+fn for_each_late_bound_region_in_item<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ mir_def_id: LocalDefId,
+ mut f: impl FnMut(ty::Region<'tcx>),
+) {
+ if !tcx.def_kind(mir_def_id).is_fn_like() {
+ return;
+ }
+
+ for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
+ let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
+ let liberated_region = tcx
+ .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region }));
+ f(liberated_region);
+ }
+}