diff options
| author | b-naber <bn263@gmx.de> | 2022-11-08 16:27:01 +0100 | 
|---|---|---|
| committer | b-naber <b_naber@gmx.de> | 2023-02-19 22:11:27 +0000 | 
| commit | 2f79f73821db1f1f169abe526fc89c8b376636ea (patch) | |
| tree | 4667b7d366487daa5f886efcb9c5c4bff7ae1c44 /compiler | |
| parent | cb35a7b4815774f7d8c8b9770df5a9719532755f (diff) | |
| download | rust-2f79f73821db1f1f169abe526fc89c8b376636ea.tar.gz rust-2f79f73821db1f1f169abe526fc89c8b376636ea.zip | |
collect region contexts during mir renumbering
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_borrowck/src/lib.rs | 90 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/nll.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/renumber.rs | 115 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/type_check/mod.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/universal_regions.rs | 117 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 7 | 
8 files changed, 347 insertions, 36 deletions
| diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index fef5f4bf466..70f6a323e88 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -25,7 +25,9 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::ChunkedBitSet; use rustc_index::vec::IndexVec; -use rustc_infer::infer::{DefiningAnchor, InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt}; +use rustc_infer::infer::{ + DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, +}; use rustc_middle::mir::{ traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents, @@ -95,6 +97,7 @@ use nll::{PoloniusOutput, ToRegionVid}; use place_ext::PlaceExt; use places_conflict::{places_conflict, PlaceConflictBias}; use region_infer::RegionInferenceContext; +use renumber::RegionCtxt; // FIXME(eddyb) perhaps move this somewhere more centrally. #[derive(Debug)] @@ -168,10 +171,10 @@ fn do_mir_borrowck<'tcx>( return_body_with_facts: bool, ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) { let def = input_body.source.with_opt_param().as_local().unwrap(); - debug!(?def); let tcx = infcx.tcx; + let infcx = BorrowckInferCtxt::new(infcx); let param_env = tcx.param_env(def.did); let mut local_names = IndexVec::from_elem(None, &input_body.local_decls); @@ -219,7 +222,7 @@ fn do_mir_borrowck<'tcx>( let mut body_owned = input_body.clone(); let mut promoted = input_promoted.clone(); let free_regions = - nll::replace_regions_in_mir(infcx, param_env, &mut body_owned, &mut promoted); + nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted); let body = &body_owned; // no further changes let location_table_owned = LocationTable::new(body); @@ -257,7 +260,7 @@ fn do_mir_borrowck<'tcx>( opt_closure_req, nll_errors, } = nll::compute_regions( - infcx, + &infcx, free_regions, body, &promoted, @@ -272,12 +275,12 @@ fn do_mir_borrowck<'tcx>( // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. - nll::dump_mir_results(infcx, &body, ®ioncx, &opt_closure_req); + nll::dump_mir_results(&infcx, &body, ®ioncx, &opt_closure_req); // We also have a `#[rustc_regions]` annotation that causes us to dump // information. nll::dump_annotation( - infcx, + &infcx, &body, ®ioncx, &opt_closure_req, @@ -321,7 +324,7 @@ fn do_mir_borrowck<'tcx>( if let Err((move_data, move_errors)) = move_data_results { let mut promoted_mbcx = MirBorrowckCtxt { - infcx, + infcx: &infcx, param_env, body: promoted_body, move_data: &move_data, @@ -350,7 +353,7 @@ fn do_mir_borrowck<'tcx>( } let mut mbcx = MirBorrowckCtxt { - infcx, + infcx: &infcx, param_env, body, move_data: &mdpe.move_data, @@ -482,22 +485,81 @@ pub struct BodyWithBorrowckFacts<'tcx> { pub location_table: LocationTable, } -struct BorrowckInferCtxt<'cx, 'tcx> { +pub struct BorrowckInferCtxt<'cx, 'tcx> { pub(crate) infcx: &'cx InferCtxt<'tcx>, #[cfg(debug_assertions)] - pub(crate) _reg_var_to_origin: RefCell<FxHashMap<ty::Region<'tcx>, NllRegionVariableOrigin>>, + pub(crate) reg_var_to_origin: RefCell<FxHashMap<ty::RegionVid, RegionCtxt>>, } impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { #[cfg(not(debug_assertions))] - pub(crate) fn _new(infcx: &'cx InferCtxt<'tcx>) -> Self { + pub(crate) fn new(infcx: &'cx InferCtxt<'tcx>) -> Self { BorrowckInferCtxt { infcx } } #[cfg(debug_assertions)] - pub(crate) fn _new(infcx: &'cx InferCtxt<'tcx>) -> Self { - BorrowckInferCtxt { infcx, _reg_var_to_origin: RefCell::new(Default::default()) } + pub(crate) fn new(infcx: &'cx InferCtxt<'tcx>) -> Self { + BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) } + } + + #[cfg(not(debug_assertions))] + pub(crate) fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { + self.infcx.next_region_var(origin) + } + + #[cfg(debug_assertions)] + pub(crate) fn next_region_var( + &self, + origin: RegionVariableOrigin, + ctxt: RegionCtxt, + ) -> ty::Region<'tcx> { + let next_region = self.infcx.next_region_var(origin); + let vid = next_region + .try_get_var() + .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + + debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); + let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); + let prev = var_to_origin.insert(vid, ctxt); + debug!("var_to_origin after insertion: {:?}", var_to_origin); + + // This only makes sense if not called in a canonicalization context. If this + // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin` + // or modify how we track nll region vars for that map. + assert!(matches!(prev, None)); + + next_region + } + + #[cfg(not(debug_assertions))] + pub(crate) fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> { + self.infcx.next_nll_region_var(origin) + } + + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + pub(crate) fn next_nll_region_var( + &self, + origin: NllRegionVariableOrigin, + ctxt: RegionCtxt, + ) -> ty::Region<'tcx> { + let next_region = self.infcx.next_nll_region_var(origin.clone()); + let vid = next_region + .try_get_var() + .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region)); + + debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin); + let mut var_to_origin = self.reg_var_to_origin.borrow_mut(); + let prev = var_to_origin.insert(vid, ctxt); + debug!("var_to_origin after insertion: {:?}", var_to_origin); + + // This only makes sense if not called in a canonicalization context. If this + // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin` + // or modify how we track nll region vars for that map. + assert!(matches!(prev, None)); + + next_region } } @@ -510,7 +572,7 @@ impl<'cx, 'tcx> Deref for BorrowckInferCtxt<'cx, 'tcx> { } struct MirBorrowckCtxt<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, + infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>, param_env: ParamEnv<'tcx>, body: &'cx Body<'tcx>, move_data: &'cx MoveData<'tcx>, diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index c71413e8e7c..c3301ac1442 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -5,7 +5,6 @@ use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexVec; -use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, @@ -37,7 +36,7 @@ use crate::{ renumber, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, universal_regions::UniversalRegions, - Upvar, + BorrowckInferCtxt, Upvar, }; pub type PoloniusOutput = Output<RustcFacts>; @@ -58,7 +57,7 @@ pub(crate) struct NllOutput<'tcx> { /// `compute_regions`. #[instrument(skip(infcx, param_env, body, promoted), level = "debug")] pub(crate) fn replace_regions_in_mir<'tcx>( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec<Promoted, Body<'tcx>>, @@ -157,7 +156,7 @@ fn populate_polonius_move_facts( /// /// This may result in errors being reported. pub(crate) fn compute_regions<'cx, 'tcx>( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, promoted: &IndexVec<Promoted, Body<'tcx>>, @@ -258,6 +257,11 @@ pub(crate) fn compute_regions<'cx, 'tcx>( borrow_set, ); + if cfg!(debug_assertions) { + let var_to_origin = infcx.reg_var_to_origin.borrow(); + debug!("var_to_origin: {:#?}", var_to_origin); + } + let mut regioncx = RegionInferenceContext::new( var_origins, universal_regions, @@ -322,7 +326,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( } pub(super) fn dump_mir_results<'tcx>( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, @@ -372,7 +376,7 @@ pub(super) fn dump_mir_results<'tcx>( #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] pub(super) fn dump_annotation<'tcx>( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 084754830bd..adf9869c34b 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,18 +1,23 @@ +<<<<<<< HEAD #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +======= +use crate::BorrowckInferCtxt; +>>>>>>> 2464f768a17 (collect region contexts during mir renumbering) use rustc_index::vec::IndexVec; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; +use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::Constant; use rustc_middle::mir::{Body, Location, Promoted}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_span::Symbol; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. #[instrument(skip(infcx, body, promoted), level = "debug")] pub fn renumber_mir<'tcx>( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec<Promoted, Body<'tcx>>, ) { @@ -29,8 +34,9 @@ pub fn renumber_mir<'tcx>( /// Replaces all regions appearing in `value` with fresh inference /// variables. +#[cfg(not(debug_assertions))] #[instrument(skip(infcx), level = "debug")] -pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> T +pub(crate) fn renumber_regions<'tcx, T>(infcx: &BorrowckInferCtxt<'_, 'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, { @@ -40,11 +46,73 @@ where }) } +/// Replaces all regions appearing in `value` with fresh inference +/// variables. +#[cfg(debug_assertions)] +#[instrument(skip(infcx), level = "debug")] +pub(crate) fn renumber_regions<'tcx, T>( + infcx: &BorrowckInferCtxt<'_, 'tcx>, + value: T, + ctxt: RegionCtxt, +) -> T +where + T: TypeFoldable<'tcx>, +{ + infcx.tcx.fold_regions(value, |_region, _depth| { + let origin = NllRegionVariableOrigin::Existential { from_forall: false }; + infcx.next_nll_region_var(origin, ctxt) + }) +} + +#[cfg(debug_assertions)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub(crate) enum RegionCtxt { + Location(Location), + TyContext(TyContext), + Free(Symbol), + Bound(Symbol), + LateBound(Symbol), + Existential(Option<Symbol>), + Placeholder(Symbol), + Unknown, +} + +#[cfg(debug_assertions)] +impl RegionCtxt { + /// Used to determine the representative of a component in the strongly connected + /// constraint graph + /// FIXME: don't use underscore here. Got a 'not used' error for some reason + pub(crate) fn _preference_value(self) -> usize { + let _anon = Symbol::intern("anon"); + + match self { + RegionCtxt::Unknown => 1, + RegionCtxt::Existential(None) => 2, + RegionCtxt::Existential(Some(_anon)) + | RegionCtxt::Free(_anon) + | RegionCtxt::Bound(_anon) + | RegionCtxt::LateBound(_anon) => 2, + RegionCtxt::Location(_) => 3, + RegionCtxt::TyContext(_) => 4, + _ => 5, + } + } +} + struct NllVisitor<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, + infcx: &'a BorrowckInferCtxt<'a, 'tcx>, } impl<'a, 'tcx> NllVisitor<'a, 'tcx> { + #[cfg(debug_assertions)] + fn renumber_regions<T>(&mut self, value: T, ctxt: RegionCtxt) -> T + where + T: TypeFoldable<'tcx>, + { + renumber_regions(self.infcx, value, ctxt) + } + + #[cfg(not(debug_assertions))] fn renumber_regions<T>(&mut self, value: T) -> T where T: TypeFoldable<'tcx>, @@ -58,13 +126,23 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { self.infcx.tcx } + #[cfg(not(debug_assertions))] #[instrument(skip(self), level = "debug")] - fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { + fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _ty_context: TyContext) { *ty = self.renumber_regions(*ty); debug!(?ty); } + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _ty_context: TyContext) { + *ty = self.renumber_regions(*ty, RegionCtxt::TyContext(_ty_context)); + + debug!(?ty); + } + + #[cfg(not(debug_assertions))] #[instrument(skip(self), level = "debug")] fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { *substs = self.renumber_regions(*substs); @@ -72,6 +150,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { debug!(?substs); } + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { + *substs = self.renumber_regions(*substs, RegionCtxt::Location(location)); + + debug!(?substs); + } + + #[cfg(not(debug_assertions))] #[instrument(skip(self), level = "debug")] fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) { let old_region = *region; @@ -80,10 +167,28 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { debug!(?region); } + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) { + let old_region = *region; + *region = self.renumber_regions(old_region, RegionCtxt::Location(location)); + + debug!(?region); + } + + #[cfg(not(debug_assertions))] #[instrument(skip(self), level = "debug")] fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) { let literal = constant.literal; constant.literal = self.renumber_regions(literal); debug!("constant: {:#?}", constant); } + + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) { + let literal = constant.literal; + constant.literal = self.renumber_regions(literal, RegionCtxt::Location(_location)); + debug!("constant: {:#?}", constant); + } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 004b945eada..8eb42ade65b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1335,11 +1335,35 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } }; let (sig, map) = tcx.replace_late_bound_regions(sig, |br| { - self.infcx.next_region_var(LateBoundRegion( - term.source_info.span, - br.kind, - LateBoundRegionConversionTime::FnCall, - )) + #[cfg(not(debug_assertions))] + { + self.infcx.next_region_var(LateBoundRegion( + term.source_info.span, + br.kind, + LateBoundRegionConversionTime::FnCall, + )) + } + + #[cfg(debug_assertions)] + { + use crate::renumber::RegionCtxt; + use rustc_span::Symbol; + + let name = match br.kind { + ty::BoundRegionKind::BrAnon(_) => Symbol::intern("anon"), + ty::BoundRegionKind::BrNamed(_, name) => name, + ty::BoundRegionKind::BrEnv => Symbol::intern("env"), + }; + + self.infcx.next_region_var( + LateBoundRegion( + term.source_info.span, + br.kind, + LateBoundRegionConversionTime::FnCall, + ), + RegionCtxt::LateBound(name), + ) + } }); debug!(?sig); // IMPORTANT: We have to prove well formed for the function signature before diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index efa5a29c5dd..919c772a203 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -20,15 +20,18 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyOwnerKind, HirId}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; +use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt, }; use rustc_middle::ty::{InternalSubsts, SubstsRef}; +use rustc_span::Symbol; use std::iter; use crate::nll::ToRegionVid; +use crate::renumber::RegionCtxt; +use crate::BorrowckInferCtxt; #[derive(Debug)] pub struct UniversalRegions<'tcx> { @@ -224,7 +227,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// signature. This will also compute the relationships that are /// known between those regions. pub fn new( - infcx: &InferCtxt<'tcx>, + infcx: &BorrowckInferCtxt<'_, 'tcx>, mir_def: ty::WithOptConstParam<LocalDefId>, param_env: ty::ParamEnv<'tcx>, ) -> Self { @@ -385,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> { } struct UniversalRegionsBuilder<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, + infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>, mir_def: ty::WithOptConstParam<LocalDefId>, mir_hir_id: HirId, param_env: ty::ParamEnv<'tcx>, @@ -403,7 +406,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars()); // Create the "global" region that is always free in all contexts: 'static. + #[cfg(not(debug_assertions))] let fr_static = self.infcx.next_nll_region_var(FR).to_region_vid(); + #[cfg(debug_assertions)] + let fr_static = self + .infcx + .next_nll_region_var(FR, RegionCtxt::Free(Symbol::intern("static"))) + .to_region_vid(); // We've now added all the global regions. The next ones we // add will be external. @@ -480,6 +489,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { LangItem::VaList, Some(self.infcx.tcx.def_span(self.mir_def.did)), ); + let reg_vid = self.infcx.next_nll_region_var(FR, RegionCtxt::Free(Symbol::intern("c-variadic")).to_region_vid(); let region = self.infcx.tcx.mk_re_var(self.infcx.next_nll_region_var(FR).to_region_vid()); let va_list_ty = @@ -491,7 +501,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } + #[cfg(not(debug_assertions))] let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid(); + #[cfg(debug_assertions)] + let fr_fn_body = self + .infcx + .next_nll_region_var(FR, RegionCtxt::Free(Symbol::intern("fn_body"))) + .to_region_vid(); + let num_universals = self.infcx.num_region_vars(); debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index); @@ -718,7 +735,8 @@ trait InferCtxtExt<'tcx> { ); } -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { + #[cfg(not(debug_assertions))] fn replace_free_regions_with_nll_infer_vars<T>( &self, origin: NllRegionVariableOrigin, @@ -727,9 +745,33 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - self.tcx.fold_regions(value, |_region, _depth| self.next_nll_region_var(origin)) + self.tcx.fold_regions(value, |_region, _depth| self.infcx.next_nll_region_var(origin)) } + #[cfg(debug_assertions)] + #[instrument(skip(self), level = "debug")] + fn replace_free_regions_with_nll_infer_vars<T>( + &self, + origin: NllRegionVariableOrigin, + value: T, + ) -> T + where + T: TypeFoldable<'tcx>, + { + self.infcx.tcx.fold_regions(value, |region, _depth| { + let name = match region.get_name() { + Some(name) => name, + _ => Symbol::intern("anon"), + }; + debug!(?region, ?name); + + let reg_var = self.next_nll_region_var(origin, RegionCtxt::Free(name)); + + reg_var + }) + } + + #[cfg(not(debug_assertions))] #[instrument(level = "debug", skip(self, indices))] fn replace_bound_regions_with_nll_infer_vars<T>( &self, @@ -752,6 +794,38 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { value } + #[cfg(debug_assertions)] + #[instrument(level = "debug", skip(self, indices))] + fn replace_bound_regions_with_nll_infer_vars<T>( + &self, + origin: NllRegionVariableOrigin, + all_outlive_scope: LocalDefId, + value: ty::Binder<'tcx, T>, + indices: &mut UniversalRegionIndices<'tcx>, + ) -> T + where + T: TypeFoldable<'tcx>, + { + let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { + debug!(?br); + let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + scope: all_outlive_scope.to_def_id(), + bound_region: br.kind, + })); + + let name = match br.kind.get_name() { + Some(name) => name, + _ => Symbol::intern("anon"), + }; + + let region_vid = self.next_nll_region_var(origin, RegionCtxt::Bound(name)); + indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); + debug!(?liberated_region, ?region_vid); + region_vid + }); + value + } + /// Finds late-bound regions that do not appear in the parameter listing and adds them to the /// indices vector. Typically, we identify late-bound regions as we process the inputs and /// outputs of the closure/function. However, sometimes there are late-bound regions which do @@ -761,6 +835,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// entries for them and store them in the indices map. This code iterates over the complete /// set of late-bound regions and checks for any that we have not yet seen, adding them to the /// inputs vector. + #[cfg(not(debug_assertions))] #[instrument(skip(self, indices))] fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( &self, @@ -792,6 +867,38 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } }); } + + /// Finds late-bound regions that do not appear in the parameter listing and adds them to the + /// indices vector. Typically, we identify late-bound regions as we process the inputs and + /// outputs of the closure/function. However, sometimes there are late-bound regions which do + /// not appear in the fn parameters but which are nonetheless in scope. The simplest case of + /// this are unused functions, like fn foo<'a>() { } (see e.g., #51351). Despite not being used, + /// users can still reference these regions (e.g., let x: &'a u32 = &22;), so we need to create + /// entries for them and store them in the indices map. This code iterates over the complete + /// set of late-bound regions and checks for any that we have not yet seen, adding them to the + /// inputs vector. + #[cfg(debug_assertions)] + #[instrument(skip(self, indices))] + fn replace_late_bound_regions_with_nll_infer_vars( + &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| { + debug!(?r); + if !indices.indices.contains_key(&r) { + let name = match r.get_name() { + Some(name) => name, + _ => Symbol::intern("anon"), + }; + + let region_vid = self.next_nll_region_var(FR, RegionCtxt::LateBound(name)); + debug!(?region_vid); + indices.insert_late_bound_region(r, region_vid.to_region_vid()); + } + }); + } } impl<'tcx> UniversalRegionIndices<'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index aa316b2dadb..64384fadc63 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1111,11 +1111,13 @@ impl<'tcx> InferCtxt<'tcx> { } /// Just a convenient wrapper of `next_region_var` for using during NLL. + #[instrument(skip(self), level = "debug")] pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> { self.next_region_var(RegionVariableOrigin::Nll(origin)) } /// Just a convenient wrapper of `next_region_var` for using during NLL. + #[instrument(skip(self), level = "debug")] pub fn next_nll_region_var_in_universe( &self, origin: NllRegionVariableOrigin, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 443c1b2d261..7f0935fb149 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1214,7 +1214,7 @@ impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> { /// Extra information passed to `visit_ty` and friends to give context /// about where the type etc appears. -#[derive(Debug)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum TyContext { LocalDecl { /// The index of the local variable we are visiting. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f8d17433cf7..c5d6df5b1ad 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1751,6 +1751,13 @@ impl<'tcx> Region<'tcx> { pub fn is_var(self) -> bool { matches!(self.kind(), ty::ReVar(_)) } + + pub fn try_get_var(self) -> Option<RegionVid> { + match self.kind() { + ty::ReVar(vid) => Some(vid), + _ => None, + } + } } /// Type utilities | 
