diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index 1f642099f0899..21d367c40cb9c 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use crate::{ borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict, @@ -18,7 +18,7 @@ use crate::{ pub(super) fn generate_constraints<'tcx>( infcx: &InferCtxt<'tcx>, - liveness_constraints: &mut LivenessValues, + liveness_constraints: &mut LivenessValues, all_facts: &mut Option, location_table: &LocationTable, body: &Body<'tcx>, @@ -43,7 +43,7 @@ struct ConstraintGeneration<'cg, 'tcx> { infcx: &'cg InferCtxt<'tcx>, all_facts: &'cg mut Option, location_table: &'cg LocationTable, - liveness_constraints: &'cg mut LivenessValues, + liveness_constraints: &'cg mut LivenessValues, borrow_set: &'cg BorrowSet<'tcx>, body: &'cg Body<'tcx>, } @@ -167,7 +167,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> { self.infcx.tcx.for_each_free_region(&live_ty, |live_region| { let vid = live_region.as_var(); - self.liveness_constraints.add_element(vid, location); + self.liveness_constraints.add_location(vid, location); }); } diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 4d620ac9de615..cfbb2766c3397 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -67,7 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { with_msg: &mut dyn FnMut(&str) -> io::Result<()>, ) -> io::Result<()> { for region in self.definitions.indices() { - let value = self.liveness_constraints.region_value_str(region); + let value = self.liveness_constraints.pretty_print_live_points(region); if value != "{}" { with_msg(&format!("{region:?} live at {value}"))?; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b1f91a0562822..f25376c248fbf 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -59,7 +59,7 @@ pub struct RegionInferenceContext<'tcx> { /// 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)`. - liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, /// The outlives constraints computed by the type-check. constraints: Frozen>, @@ -332,7 +332,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, universe_causes: FxIndexMap>, type_tests: Vec>, - liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, elements: &Rc, live_loans: SparseBitMatrix, ) -> Self { @@ -359,7 +359,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut scc_values = RegionValues::new(elements, universal_regions.len(), &placeholder_indices); - for region in liveness_constraints.rows() { + for region in liveness_constraints.regions() { let scc = constraint_sccs.scc(region); scc_values.merge_liveness(scc, region, &liveness_constraints); } @@ -1963,15 +1963,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { None } - /// Finds some region R such that `fr1: R` and `R` is live at `elem`. + /// Finds some region R such that `fr1: R` and `R` is live at `location`. #[instrument(skip(self), level = "trace", ret)] - pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { + pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { trace!(scc = ?self.constraint_sccs.scc(fr1)); trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]); self.find_constraint_paths_between_regions(fr1, |r| { - // First look for some `r` such that `fr1: r` and `r` is live at `elem` - trace!(?r, liveness_constraints=?self.liveness_constraints.region_value_str(r)); - self.liveness_constraints.contains(r, elem) + // First look for some `r` such that `fr1: r` and `r` is live at `location` + trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); + self.liveness_constraints.is_live_at(r, location) }) .or_else(|| { // If we fail to find that, we may find some `r` such that diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 38452df32e9ed..93f5fbd003961 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -116,65 +116,68 @@ pub(crate) enum RegionElement { PlaceholderRegion(ty::PlaceholderRegion), } -/// When we initially compute liveness, we use an interval matrix storing -/// liveness ranges for each region-vid. -pub(crate) struct LivenessValues { +/// Records the CFG locations where each region is live. When we initially compute liveness, we use +/// an interval matrix storing liveness ranges for each region-vid. +pub(crate) struct LivenessValues { elements: Rc, - points: SparseIntervalMatrix, + points: SparseIntervalMatrix, } -impl LivenessValues { - /// Creates a new set of "region values" that tracks causal information. - /// Each of the regions in num_region_variables will be initialized with an - /// empty set of points and no causal information. +impl LivenessValues { + /// Create an empty map of regions to locations where they're live. pub(crate) fn new(elements: Rc) -> Self { Self { points: SparseIntervalMatrix::new(elements.num_points), elements } } /// Iterate through each region that has a value in this set. - pub(crate) fn rows(&self) -> impl Iterator { + pub(crate) fn regions(&self) -> impl Iterator { self.points.rows() } - /// Adds the given element to the value for the given region. Returns whether - /// the element is newly added (i.e., was not already present). - pub(crate) fn add_element(&mut self, row: N, location: Location) -> bool { - debug!("LivenessValues::add(r={:?}, location={:?})", row, location); - let index = self.elements.point_from_location(location); - self.points.insert(row, index) + /// Records `region` as being live at the given `location`. + pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) { + debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); + let point = self.elements.point_from_location(location); + self.points.insert(region, point); } - /// Adds all the elements in the given bit array into the given - /// region. Returns whether any of them are newly added. - pub(crate) fn add_elements(&mut self, row: N, locations: &IntervalSet) -> bool { - debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); - self.points.union_row(row, locations) + /// Records `region` as being live at all the given `points`. + pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet) { + debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); + self.points.union_row(region, points); } - /// Adds all the control-flow points to the values for `r`. - pub(crate) fn add_all_points(&mut self, row: N) { - self.points.insert_all_into_row(row); + /// Records `region` as being live at all the control-flow points. + pub(crate) fn add_all_points(&mut self, region: RegionVid) { + self.points.insert_all_into_row(region); } - /// Returns `true` if the region `r` contains the given element. - pub(crate) fn contains(&self, row: N, location: Location) -> bool { - let index = self.elements.point_from_location(location); - self.points.row(row).is_some_and(|r| r.contains(index)) + /// Returns whether `region` is marked live at the given `location`. + pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { + let point = self.elements.point_from_location(location); + self.points.row(region).is_some_and(|r| r.contains(point)) + } + + /// Returns whether `region` is marked live at any location. + pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool { + self.live_points(region).next().is_some() } - /// Returns an iterator of all the elements contained by the region `r` - pub(crate) fn get_elements(&self, row: N) -> impl Iterator + '_ { + /// Returns an iterator of all the points where `region` is live. + fn live_points(&self, region: RegionVid) -> impl Iterator + '_ { self.points - .row(row) + .row(region) .into_iter() .flat_map(|set| set.iter()) - .take_while(move |&p| self.elements.point_in_range(p)) - .map(move |p| self.elements.to_location(p)) + .take_while(|&p| self.elements.point_in_range(p)) } - /// Returns a "pretty" string value of the region. Meant for debugging. - pub(crate) fn region_value_str(&self, r: N) -> String { - region_value_str(self.get_elements(r).map(RegionElement::Location)) + /// For debugging purposes, returns a pretty-printed string of the points where the `region` is + /// live. + pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String { + pretty_print_region_elements( + self.live_points(region).map(|p| RegionElement::Location(self.elements.to_location(p))), + ) } #[inline] @@ -307,7 +310,7 @@ impl RegionValues { /// `self[to] |= values[from]`, essentially: that is, take all the /// elements for the region `from` from `values` and add them to /// the region `to` in `self`. - pub(crate) fn merge_liveness(&mut self, to: N, from: M, values: &LivenessValues) { + pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) { if let Some(set) = values.points.row(from) { self.points.union_row(to, set); } @@ -376,7 +379,7 @@ impl RegionValues { /// Returns a "pretty" string value of the region. Meant for debugging. pub(crate) fn region_value_str(&self, r: N) -> String { - region_value_str(self.elements_contained_in(r)) + pretty_print_region_elements(self.elements_contained_in(r)) } } @@ -420,11 +423,12 @@ impl ToElementIndex for ty::PlaceholderRegion { } } -pub(crate) fn location_set_str( +/// For debugging purposes, returns a pretty-printed string of the given points. +pub(crate) fn pretty_print_points( elements: &RegionValueElements, points: impl IntoIterator, ) -> String { - region_value_str( + pretty_print_region_elements( points .into_iter() .take_while(|&p| elements.point_in_range(p)) @@ -433,7 +437,8 @@ pub(crate) fn location_set_str( ) } -fn region_value_str(elements: impl IntoIterator) -> String { +/// For debugging purposes, returns a pretty-printed string of the given region elements. +fn pretty_print_region_elements(elements: impl IntoIterator) -> String { let mut result = String::new(); result.push('{'); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index e616449ccd412..2ef4cf6768235 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -550,7 +550,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { dropped_local, dropped_ty, drop_locations, - values::location_set_str(self.elements, live_at.iter()), + values::pretty_print_points(self.elements, live_at.iter()), ); let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ @@ -599,7 +599,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { debug!("make_all_regions_live(value={:?})", value); debug!( "make_all_regions_live: live_at={}", - values::location_set_str(elements, live_at.iter()), + values::pretty_print_points(elements, live_at.iter()), ); // When using `-Zpolonius=next`, we want to record the loans that flow into this value's @@ -618,7 +618,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { .borrowck_context .constraints .liveness_constraints - .add_elements(live_region_vid, live_at); + .add_points(live_region_vid, live_at); // There can only be inflowing loans for this region when we are using // `-Zpolonius=next`. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 608d010394f66..f0e35bdb75f55 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -318,7 +318,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { .borrowck_context .constraints .liveness_constraints - .add_element(live_region_vid, location); + .add_location(live_region_vid, location); }); // HACK(compiler-errors): Constants that are gathered into Body.required_consts @@ -592,16 +592,16 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for region in liveness_constraints.rows() { + for region in liveness_constraints.regions() { // If the region is live at at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region // at the location provided as an argument to this method - if liveness_constraints.get_elements(region).next().is_some() { + if liveness_constraints.is_live_anywhere(region) { self.cx .borrowck_context .constraints .liveness_constraints - .add_element(region, location); + .add_location(region, location); } } } @@ -899,7 +899,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { /// not otherwise appear in the MIR -- in particular, the /// late-bound regions that it instantiates at call-sites -- and /// hence it must report on their liveness constraints. - pub(crate) liveness_constraints: LivenessValues, + pub(crate) liveness_constraints: LivenessValues, pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>, @@ -1443,7 +1443,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context .constraints .liveness_constraints - .add_element(region_vid, term_location); + .add_location(region_vid, term_location); } self.check_call_inputs(body, term, func, &sig, args, term_location, *call_source);