From f27bdf175034bd0455eb960fc0dc8262484f187b Mon Sep 17 00:00:00 2001 From: Michael Goulet <michael@errs.io> Date: Mon, 31 Oct 2022 03:28:05 +0000 Subject: [PATCH] Collect late-bound regions from all closure parents in `closure_mapping` --- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../rustc_borrowck/src/universal_regions.rs | 82 ++++++++++--------- .../binder/nested-closures-regions.rs | 9 ++ .../binder/nested-closures-regions.stderr | 38 +++++++++ 4 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 src/test/ui/closures/binder/nested-closures-regions.rs create mode 100644 src/test/ui/closures/binder/nested-closures-regions.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8b63294fbab..0e7f243bcf3 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2314,7 +2314,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx tcx, closure_substs, self.num_external_vids, - tcx.typeck_root_def_id(closure_def_id), + closure_def_id.expect_local(), ); debug!("apply_requirements: closure_mapping={:?}", closure_mapping); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 51439dec440..0f300564c20 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -243,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); @@ -251,9 +251,13 @@ impl<'tcx> UniversalRegions<'tcx> { region_mapping.push(fr); }); - for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| { - region_mapping.push(r); - }); + for_each_late_bound_region_in_scope( + tcx, + tcx.local_parent(closure_def_id), + |r| { + region_mapping.push(r); + }, + ); assert_eq!( region_mapping.len(), @@ -341,9 +345,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_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::Generator(def_id, substs, _) => { @@ -356,9 +359,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_scope(tcx, def_id.expect_local(), |r| { + err.note(&format!("late-bound region is {:?}", self.to_region_vid(r))); }); } DefiningTy::FnDef(def_id, substs) => { @@ -749,28 +751,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { #[instrument(skip(self, indices))] fn replace_late_bound_regions_with_nll_infer_vars( &self, - mut mir_def_id: LocalDefId, + 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()); - - // Walk up the tree, collecting late-bound regions until we hit the typeck root - loop { - for_each_late_bound_region_defined_on(self.tcx, mir_def_id.to_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()); - } - }); - - if mir_def_id.to_def_id() == typeck_root_def_id { - break; - } else { - mir_def_id = self.tcx.parent(mir_def_id.to_def_id()).expect_local(); + for_each_late_bound_region_in_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()); } - } + }); } } @@ -814,18 +805,31 @@ 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 fn_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_scope<'tcx>( tcx: TyCtxt<'tcx>, - fn_def_id: DefId, + mut mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(fn_def_id.expect_local())) - { - let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; - let liberated_region = - tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, bound_region })); - 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 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); + } + + if mir_def_id.to_def_id() == typeck_root_def_id { + break; + } else { + mir_def_id = tcx.local_parent(mir_def_id); + } } } diff --git a/src/test/ui/closures/binder/nested-closures-regions.rs b/src/test/ui/closures/binder/nested-closures-regions.rs new file mode 100644 index 00000000000..6bfc6c80b78 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] +#![feature(rustc_attrs)] + +#[rustc_regions] +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/src/test/ui/closures/binder/nested-closures-regions.stderr b/src/test/ui/closures/binder/nested-closures-regions.stderr new file mode 100644 index 00000000000..b385e0ed6e0 --- /dev/null +++ b/src/test/ui/closures/binder/nested-closures-regions.stderr @@ -0,0 +1,38 @@ +note: external requirements + --> $DIR/nested-closures-regions.rs:8:24 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0}::{closure#0} with closure substs [ + i8, + extern "rust-call" fn((&(),)), + (), + ] + = note: late-bound region is '_#4r + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + = note: where '_#2r: '_#1r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:8:5 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0} with closure substs [ + i8, + extern "rust-call" fn(()), + (), + ] + = note: late-bound region is '_#2r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:7:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = note: defining type: main +