From 66c5d5b70697dd98468a88b455dc99681c810db1 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 28 Dec 2019 19:35:18 -0600 Subject: [PATCH] Privatize the fields of RegionInferenceContext --- .../borrow_check/diagnostics/region_errors.rs | 18 +++--- .../borrow_check/diagnostics/region_name.rs | 12 ++-- .../borrow_check/diagnostics/var_name.rs | 16 ++--- .../borrow_check/region_infer/mod.rs | 63 ++++++++++++++----- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 5980ff00732..dcba790ad7e 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -113,18 +113,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// one (e.g., this is just some random part of the CFG). pub(super) fn to_error_region(&self, r: RegionVid) -> Option> { self.to_error_region_vid(r) - .and_then(|r| self.nonlexical_regioncx.definitions[r].external_name) + .and_then(|r| self.nonlexical_regioncx.region_definition(r).external_name) } /// Returns the `RegionVid` corresponding to the region returned by /// `to_error_region`. pub(super) fn to_error_region_vid(&self, r: RegionVid) -> Option { - if self.nonlexical_regioncx.universal_regions.is_universal_region(r) { + if self.nonlexical_regioncx.universal_regions().is_universal_region(r) { Some(r) } else { - let r_scc = self.nonlexical_regioncx.constraint_sccs.scc(r); let upper_bound = self.nonlexical_regioncx.universal_upper_bound(r); - if self.nonlexical_regioncx.scc_values.contains(r_scc, upper_bound) { + + if self.nonlexical_regioncx.upper_bound_in_region_scc(r, upper_bound) { self.to_error_region_vid(upper_bound) } else { None @@ -137,7 +137,7 @@ fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) { if let ty::BoundRegion::BrEnv = free_region.bound_region { if let DefiningTy::Closure(def_id, substs) = - self.nonlexical_regioncx.universal_regions.defining_ty + self.nonlexical_regioncx.universal_regions().defining_ty { let closure_kind_ty = substs.as_closure().kind_ty(def_id, self.infcx.tcx); return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind(); @@ -302,8 +302,8 @@ pub(in crate::borrow_check) fn report_error( } let (fr_is_local, outlived_fr_is_local): (bool, bool) = ( - self.nonlexical_regioncx.universal_regions.is_local_free_region(fr), - self.nonlexical_regioncx.universal_regions.is_local_free_region(outlived_fr), + self.nonlexical_regioncx.universal_regions().is_local_free_region(fr), + self.nonlexical_regioncx.universal_regions().is_local_free_region(outlived_fr), ); debug!( @@ -378,7 +378,7 @@ fn report_fnmut_error( // We should check if the return type of this closure is in fact a closure - in that // case, we can special case the error further. let return_type_is_closure = - self.nonlexical_regioncx.universal_regions.unnormalized_output_ty.is_closure(); + self.nonlexical_regioncx.universal_regions().unnormalized_output_ty.is_closure(); let message = if return_type_is_closure { "returns a closure that contains a reference to a captured variable, which then \ escapes the closure body" @@ -445,7 +445,7 @@ fn report_escaping_data_error( errci.outlived_fr, ); - let escapes_from = match self.nonlexical_regioncx.universal_regions.defining_ty { + let escapes_from = match self.nonlexical_regioncx.universal_regions().defining_ty { DefiningTy::Closure(..) => "closure", DefiningTy::Generator(..) => "generator", DefiningTy::FnDef(..) => "function", diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index e5dfb0f70ee..b6bfa30b4dc 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -191,7 +191,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ) -> Option { debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter); - assert!(self.nonlexical_regioncx.universal_regions.is_universal_region(fr)); + assert!(self.nonlexical_regioncx.universal_regions().is_universal_region(fr)); if let Some(value) = renctx.get(&fr) { return Some(value.clone()); @@ -277,7 +277,7 @@ fn give_name_from_error_region( .hir() .as_local_hir_id(self.mir_def_id) .expect("non-local mir"); - let def_ty = self.nonlexical_regioncx.universal_regions.defining_ty; + let def_ty = self.nonlexical_regioncx.universal_regions().defining_ty; if let DefiningTy::Closure(def_id, substs) = def_ty { let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = @@ -345,11 +345,11 @@ fn give_name_if_anonymous_region_appears_in_arguments( renctx: &mut RegionErrorNamingCtx, ) -> Option { let implicit_inputs = - self.nonlexical_regioncx.universal_regions.defining_ty.implicit_inputs(); + self.nonlexical_regioncx.universal_regions().defining_ty.implicit_inputs(); let argument_index = self.nonlexical_regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?; - let arg_ty = self.nonlexical_regioncx.universal_regions.unnormalized_input_tys + let arg_ty = self.nonlexical_regioncx.universal_regions().unnormalized_input_tys [implicit_inputs + argument_index]; if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index, renctx) @@ -684,7 +684,7 @@ fn give_name_if_anonymous_region_appears_in_output( ) -> Option { let tcx = self.infcx.tcx; - let return_ty = self.nonlexical_regioncx.universal_regions.unnormalized_output_ty; + let return_ty = self.nonlexical_regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { return None; @@ -734,7 +734,7 @@ fn give_name_if_anonymous_region_appears_in_yield_ty( ) -> Option { // Note: generators from `async fn` yield `()`, so we don't have to // worry about them here. - let yield_ty = self.nonlexical_regioncx.universal_regions.yield_ty?; + let yield_ty = self.nonlexical_regioncx.universal_regions().yield_ty?; debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,); let tcx = self.infcx.tcx; diff --git a/src/librustc_mir/borrow_check/diagnostics/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs index 9e3d2a7d5f6..5f3585ce8b1 100644 --- a/src/librustc_mir/borrow_check/diagnostics/var_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/var_name.rs @@ -16,7 +16,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option<(Option, Span)> { debug!("get_var_name_and_span_for_region(fr={:?})", fr); - assert!(self.universal_regions.is_universal_region(fr)); + assert!(self.universal_regions().is_universal_region(fr)); debug!("get_var_name_and_span_for_region: attempting upvar"); self.get_upvar_index_for_region(tcx, fr) @@ -35,7 +35,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Search the upvars (if any) to find one that references fr. Return its index. crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option { let upvar_index = - self.universal_regions.defining_ty.upvar_tys(tcx).position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.to_region_vid(); @@ -44,7 +44,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions.defining_ty.upvar_tys(tcx).nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys(tcx).nth(upvar_index); debug!( "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}", @@ -85,9 +85,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, fr: RegionVid, ) -> Option { - let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); + let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); let argument_index = - self.universal_regions.unnormalized_input_tys.iter().skip(implicit_inputs).position( + self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( |arg_ty| { debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty); tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) @@ -96,7 +96,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!( "get_argument_index_for_region: found {:?} in argument {} which has type {:?}", - fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index], + fr, + argument_index, + self.universal_regions().unnormalized_input_tys[argument_index], ); Some(argument_index) @@ -110,7 +112,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { local_names: &IndexVec>, argument_index: usize, ) -> (Option, Span) { - let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); + let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); let argument_local = Local::new(implicit_inputs + argument_index + 1); debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local); diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 406b28e1e32..359f75cac83 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -44,49 +44,48 @@ pub struct RegionInferenceContext<'tcx> { /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came /// from as well as its final inferred value. - pub(in crate::borrow_check) definitions: IndexVec>, + definitions: IndexVec>, /// The liveness constraints added to each region. For most /// regions, these start out empty and steadily grow, though for /// each universally quantified region R they start out containing /// the entire CFG and `end(R)`. - pub(in crate::borrow_check) liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, /// The outlives constraints computed by the type-check. - pub(in crate::borrow_check) constraints: Rc, + constraints: Rc, /// The constraint-set, but in graph form, making it easy to traverse /// the constraints adjacent to a particular region. Used to construct /// the SCC (see `constraint_sccs`) and for error reporting. - pub(in crate::borrow_check) constraint_graph: Rc, + constraint_graph: Rc, /// The SCC computed from `constraints` and the constraint /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to /// compute the values of each region. - pub(in crate::borrow_check) constraint_sccs: Rc>, + constraint_sccs: Rc>, /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` /// exists if `B: A`. Computed lazilly. - pub(in crate::borrow_check) rev_constraint_graph: Option>>, + rev_constraint_graph: Option>>, /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. - pub(in crate::borrow_check) member_constraints: - Rc>, + member_constraints: Rc>, /// Records the member constraints that we applied to each scc. /// This is useful for error reporting. Once constraint /// propagation is done, this vector is sorted according to /// `member_region_scc`. - pub(in crate::borrow_check) member_constraints_applied: Vec, + member_constraints_applied: Vec, /// Map closure bounds to a `Span` that should be used for error reporting. - pub(in crate::borrow_check) closure_bounds_mapping: + closure_bounds_mapping: FxHashMap>, /// Contains the minimum universe of any variable within the same /// SCC. We will ensure that no SCC contains values that are not /// visible from this index. - pub(in crate::borrow_check) scc_universes: IndexVec, + scc_universes: IndexVec, /// Contains a "representative" from each SCC. This will be the /// minimal RegionVid belonging to that universe. It is used as a @@ -95,23 +94,23 @@ pub struct RegionInferenceContext<'tcx> { /// of its SCC and be sure that -- if they have the same repr -- /// they *must* be equal (though not having the same repr does not /// mean they are unequal). - pub(in crate::borrow_check) scc_representatives: IndexVec, + scc_representatives: IndexVec, /// The final inferred values of the region variables; we compute /// one value per SCC. To get the value for any given *region*, /// you first find which scc it is a part of. - pub(in crate::borrow_check) scc_values: RegionValues, + scc_values: RegionValues, /// Type constraints that we check after solving. - pub(in crate::borrow_check) type_tests: Vec>, + type_tests: Vec>, /// Information about the universally quantified regions in scope /// on this function. - pub(in crate::borrow_check) universal_regions: Rc>, + universal_regions: Rc>, /// Information about how the universally quantified regions in /// scope on this function relate to one another. - pub(in crate::borrow_check) universal_region_relations: Rc>, + universal_region_relations: Rc>, } /// Each time that `apply_member_constraint` is successful, it appends @@ -1840,6 +1839,38 @@ fn check_member_constraints( .unwrap() } + /// Get the region outlived by `longer_fr` and live at `element`. + crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid { + match element { + RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), + RegionElement::RootUniversalRegion(r) => r, + RegionElement::PlaceholderRegion(error_placeholder) => self + .definitions + .iter_enumerated() + .filter_map(|(r, definition)| match definition.origin { + NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), + _ => None, + }) + .next() + .unwrap(), + } + } + + /// Get the region definition of `r`. + crate fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { + &self.definitions[r] + } + + /// Check if the SCC of `r` contains `upper`. + crate fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { + let r_scc = self.constraint_sccs.scc(r); + self.scc_values.contains(r_scc, upper) + } + + crate fn universal_regions(&self) -> Rc> { + self.universal_regions.clone() + } + /// Tries to find the best constraint to blame for the fact that /// `R: from_region`, where `R` is some region that meets /// `target_test`. This works by following the constraint graph,