Make drop-use fact collection simpler for polonius

This shunts all the complexity of siphoning off the drop-use facts
into `LivenessResults::add_extra_drop_facts()`, which may or may
not be a good approach.
This commit is contained in:
Amanda Stjerna 2024-05-28 15:49:22 +02:00
parent 077a8219b0
commit e15564672e
4 changed files with 34 additions and 41 deletions

View File

@ -14,7 +14,6 @@ use std::rc::Rc;
use crate::{ use crate::{
constraints::OutlivesConstraintSet, constraints::OutlivesConstraintSet,
facts::{AllFacts, AllFactsExt}, facts::{AllFacts, AllFactsExt},
location::LocationTable,
region_infer::values::LivenessValues, region_infer::values::LivenessValues,
universal_regions::UniversalRegions, universal_regions::UniversalRegions,
}; };
@ -39,7 +38,6 @@ pub(super) fn generate<'mir, 'tcx>(
elements: &Rc<DenseLocationMap>, elements: &Rc<DenseLocationMap>,
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
location_table: &LocationTable,
use_polonius: bool, use_polonius: bool,
) { ) {
debug!("liveness::generate"); debug!("liveness::generate");
@ -53,11 +51,9 @@ pub(super) fn generate<'mir, 'tcx>(
compute_relevant_live_locals(typeck.tcx(), &free_regions, body); compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
let polonius_drop_used = facts_enabled.then(|| { if facts_enabled {
let mut drop_used = Vec::new(); polonius::populate_access_facts(typeck, body, move_data);
polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used); };
drop_used
});
trace::trace( trace::trace(
typeck, typeck,
@ -67,7 +63,6 @@ pub(super) fn generate<'mir, 'tcx>(
move_data, move_data,
relevant_live_locals, relevant_live_locals,
boring_locals, boring_locals,
polonius_drop_used,
); );
// Mark regions that should be live where they appear within rvalues or within a call: like // Mark regions that should be live where they appear within rvalues or within a call: like

View File

@ -14,7 +14,7 @@ struct UseFactsExtractor<'me, 'tcx> {
var_defined_at: &'me mut VarPointRelation, var_defined_at: &'me mut VarPointRelation,
var_used_at: &'me mut VarPointRelation, var_used_at: &'me mut VarPointRelation,
location_table: &'me LocationTable, location_table: &'me LocationTable,
var_dropped_at: &'me mut Vec<(Local, Location)>, var_dropped_at: &'me mut VarPointRelation,
move_data: &'me MoveData<'tcx>, move_data: &'me MoveData<'tcx>,
path_accessed_at_base: &'me mut PathPointRelation, path_accessed_at_base: &'me mut PathPointRelation,
} }
@ -37,7 +37,7 @@ impl<'tcx> UseFactsExtractor<'_, 'tcx> {
fn insert_drop_use(&mut self, local: Local, location: Location) { fn insert_drop_use(&mut self, local: Local, location: Location) {
debug!("UseFactsExtractor::insert_drop_use()"); debug!("UseFactsExtractor::insert_drop_use()");
self.var_dropped_at.push((local, location)); self.var_dropped_at.push((local, self.location_to_index(location)));
} }
fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
@ -85,33 +85,22 @@ impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> {
pub(super) fn populate_access_facts<'a, 'tcx>( pub(super) fn populate_access_facts<'a, 'tcx>(
typeck: &mut TypeChecker<'a, 'tcx>, typeck: &mut TypeChecker<'a, 'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
location_table: &LocationTable,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
// FIXME: this is an inelegant way of squirreling away a
// copy of `var_dropped_at` in the original `Location` format
// for later use in `trace::trace()`, which updates some liveness-
// internal data based on what Polonius saw.
// Ideally, that part would access the Polonius facts directly, and this
// would be regular facts gathering.
dropped_at: &mut Vec<(Local, Location)>,
) { ) {
debug!("populate_access_facts()"); debug!("populate_access_facts()");
let location_table = typeck.borrowck_context.location_table;
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
let mut extractor = UseFactsExtractor { let mut extractor = UseFactsExtractor {
var_defined_at: &mut facts.var_defined_at, var_defined_at: &mut facts.var_defined_at,
var_used_at: &mut facts.var_used_at, var_used_at: &mut facts.var_used_at,
var_dropped_at: dropped_at, var_dropped_at: &mut facts.var_dropped_at,
path_accessed_at_base: &mut facts.path_accessed_at_base, path_accessed_at_base: &mut facts.path_accessed_at_base,
location_table, location_table,
move_data, move_data,
}; };
extractor.visit_body(body); extractor.visit_body(body);
facts.var_dropped_at.extend(
dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))),
);
for (local, local_decl) in body.local_decls.iter_enumerated() { for (local, local_decl) in body.local_decls.iter_enumerated() {
debug!( debug!(
"add use_of_var_derefs_origin facts - local={:?}, type={:?}", "add use_of_var_derefs_origin facts - local={:?}, type={:?}",

View File

@ -16,6 +16,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::ResultsCursor; use rustc_mir_dataflow::ResultsCursor;
use crate::location::RichLocation;
use crate::{ use crate::{
region_infer::values::{self, LiveLoans}, region_infer::values::{self, LiveLoans},
type_check::liveness::local_use_map::LocalUseMap, type_check::liveness::local_use_map::LocalUseMap,
@ -46,7 +47,6 @@ pub(super) fn trace<'mir, 'tcx>(
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
relevant_live_locals: Vec<Local>, relevant_live_locals: Vec<Local>,
boring_locals: Vec<Local>, boring_locals: Vec<Local>,
polonius_drop_used: Option<Vec<(Local, Location)>>,
) { ) {
let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);
@ -81,6 +81,8 @@ pub(super) fn trace<'mir, 'tcx>(
borrowck_context.constraints.liveness_constraints.loans = Some(live_loans); borrowck_context.constraints.liveness_constraints.loans = Some(live_loans);
}; };
let polonius_facts_gathered = typeck.borrowck_context.all_facts.is_some();
let cx = LivenessContext { let cx = LivenessContext {
typeck, typeck,
body, body,
@ -93,8 +95,8 @@ pub(super) fn trace<'mir, 'tcx>(
let mut results = LivenessResults::new(cx); let mut results = LivenessResults::new(cx);
if let Some(drop_used) = polonius_drop_used { if polonius_facts_gathered {
results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect()) results.add_extra_drop_facts(relevant_live_locals.iter().copied().collect());
} }
results.compute_for_all_locals(relevant_live_locals); results.compute_for_all_locals(relevant_live_locals);
@ -218,17 +220,32 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
/// ///
/// Add facts for all locals with free regions, since regions may outlive /// Add facts for all locals with free regions, since regions may outlive
/// the function body only at certain nodes in the CFG. /// the function body only at certain nodes in the CFG.
fn add_extra_drop_facts( fn add_extra_drop_facts(&mut self, relevant_live_locals: FxIndexSet<Local>) {
&mut self, let drop_used = self
drop_used: Vec<(Local, Location)>, .cx
relevant_live_locals: FxIndexSet<Local>, .typeck
) { .borrowck_context
.all_facts
.as_ref()
.map(|facts| facts.var_dropped_at.clone())
.into_iter()
.flatten();
let locations = IntervalSet::new(self.cx.elements.num_points()); let locations = IntervalSet::new(self.cx.elements.num_points());
for (local, location) in drop_used { for (local, location_index) in drop_used {
if !relevant_live_locals.contains(&local) { if !relevant_live_locals.contains(&local) {
let local_ty = self.cx.body.local_decls[local].ty; let local_ty = self.cx.body.local_decls[local].ty;
if local_ty.has_free_regions() { if local_ty.has_free_regions() {
let location = match self
.cx
.typeck
.borrowck_context
.location_table
.to_location(location_index)
{
RichLocation::Start(l) => l,
RichLocation::Mid(l) => l,
};
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
} }
} }

View File

@ -188,15 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
checker.check_signature_annotation(body); checker.check_signature_annotation(body);
liveness::generate( liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius);
&mut checker,
body,
elements,
flow_inits,
move_data,
location_table,
use_polonius,
);
translate_outlives_facts(&mut checker); translate_outlives_facts(&mut checker);
let opaque_type_values = infcx.take_opaque_types(); let opaque_type_values = infcx.take_opaque_types();