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 rustc_index::bit_set::SparseBitMatrix;
use rustc_index::interval::SparseIntervalMatrix;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeVisitable};
use rustc_mir_dataflow::points::PointIndex;
use super::{ConstraintDirection, PoloniusContext};
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");
}
/// 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

View file

@ -57,7 +57,7 @@ use crate::universal_regions::UniversalRegions;
pub(crate) struct PoloniusContext {
/// 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.
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
/// liveness constraints depends on the variance of types with respect to each contained region.
@ -79,11 +79,8 @@ enum ConstraintDirection {
}
impl PoloniusContext {
pub(crate) fn new(num_regions: usize) -> PoloniusContext {
Self {
live_region_variances: BTreeMap::new(),
live_regions: SparseBitMatrix::new(num_regions),
}
pub(crate) fn new() -> PoloniusContext {
Self { live_region_variances: BTreeMap::new(), live_regions: None }
}
/// 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.
pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + '_ {
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);
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(num_regions))
Some(PoloniusContext::new())
} else {
None
};
@ -187,6 +186,12 @@ pub(crate) fn type_check<'a, 'tcx>(
let opaque_type_values =
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 {
constraints,
universal_region_relations,