1
Fork 0

finish filling polonius context

transpose liveness matrix and record live regions at the end of MIR typeck
This commit is contained in:
Rémy Rakic 2024-12-22 23:25:19 +00:00
parent cbdac2f0e9
commit 6e88db90c2
4 changed files with 40 additions and 8 deletions

View file

@ -1,7 +1,10 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use rustc_index::bit_set::SparseBitMatrix;
use rustc_index::interval::SparseIntervalMatrix;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeVisitable};
use rustc_mir_dataflow::points::PointIndex;
use super::{ConstraintDirection, PoloniusContext}; use super::{ConstraintDirection, PoloniusContext};
use crate::universal_regions::UniversalRegions; use crate::universal_regions::UniversalRegions;
@ -22,6 +25,25 @@ impl PoloniusContext {
}; };
extractor.relate(value, value).expect("Can't have a type error relating to itself"); extractor.relate(value, value).expect("Can't have a type error relating to itself");
} }
/// Unlike NLLs, in polonius we traverse the cfg to look for regions live across an edge, so we
/// need to transpose the "points where each region is live" matrix to a "live regions per point"
/// matrix.
// FIXME: avoid this conversion by always storing liveness data in this shape in the rest of
// borrowck.
pub(crate) fn record_live_regions_per_point(
&mut self,
num_regions: usize,
points_per_live_region: &SparseIntervalMatrix<RegionVid, PointIndex>,
) {
let mut live_regions_per_point = SparseBitMatrix::new(num_regions);
for region in points_per_live_region.rows() {
for point in points_per_live_region.row(region).unwrap().iter() {
live_regions_per_point.insert(point, region);
}
}
self.live_regions = Some(live_regions_per_point);
}
} }
/// Extracts variances for regions contained within types. Follows the same structure as /// Extracts variances for regions contained within types. Follows the same structure as

View file

@ -57,7 +57,7 @@ use crate::universal_regions::UniversalRegions;
pub(crate) struct PoloniusContext { pub(crate) struct PoloniusContext {
/// The set of regions that are live at a given point in the CFG, used to create localized /// The set of regions that are live at a given point in the CFG, used to create localized
/// outlives constraints between regions that are live at connected points in the CFG. /// outlives constraints between regions that are live at connected points in the CFG.
live_regions: SparseBitMatrix<PointIndex, RegionVid>, live_regions: Option<SparseBitMatrix<PointIndex, RegionVid>>,
/// The expected edge direction per live region: the kind of directed edge we'll create as /// The expected edge direction per live region: the kind of directed edge we'll create as
/// liveness constraints depends on the variance of types with respect to each contained region. /// liveness constraints depends on the variance of types with respect to each contained region.
@ -79,11 +79,8 @@ enum ConstraintDirection {
} }
impl PoloniusContext { impl PoloniusContext {
pub(crate) fn new(num_regions: usize) -> PoloniusContext { pub(crate) fn new() -> PoloniusContext {
Self { Self { live_region_variances: BTreeMap::new(), live_regions: None }
live_region_variances: BTreeMap::new(),
live_regions: SparseBitMatrix::new(num_regions),
}
} }
/// Creates a constraint set for `-Zpolonius=next` by: /// Creates a constraint set for `-Zpolonius=next` by:

View file

@ -99,6 +99,14 @@ impl LivenessValues {
} }
} }
/// Returns the liveness matrix of points where each region is live. Panics if the liveness
/// values have been created without any per-point data (that is, for promoteds).
pub(crate) fn points(&self) -> &SparseIntervalMatrix<RegionVid, PointIndex> {
self.points
.as_ref()
.expect("this `LivenessValues` wasn't created using `with_specific_points`")
}
/// Iterate through each region that has a value in this set. /// Iterate through each region that has a value in this set.
pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ { pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ {
self.points.as_ref().expect("use with_specific_points").rows() self.points.as_ref().expect("use with_specific_points").rows()

View file

@ -150,8 +150,7 @@ pub(crate) fn type_check<'a, 'tcx>(
debug!(?normalized_inputs_and_output); debug!(?normalized_inputs_and_output);
let mut polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { let mut polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
let num_regions = infcx.num_region_vars(); Some(PoloniusContext::new())
Some(PoloniusContext::new(num_regions))
} else { } else {
None None
}; };
@ -187,6 +186,12 @@ pub(crate) fn type_check<'a, 'tcx>(
let opaque_type_values = let opaque_type_values =
opaque_types::take_opaques_and_register_member_constraints(&mut typeck); opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
if let Some(polonius_context) = typeck.polonius_context.as_mut() {
let num_regions = infcx.num_region_vars();
let points_per_live_region = typeck.constraints.liveness_constraints.points();
polonius_context.record_live_regions_per_point(num_regions, points_per_live_region);
}
MirTypeckResults { MirTypeckResults {
constraints, constraints,
universal_region_relations, universal_region_relations,