clean up emit_access_facts

- remove dependency on `TypeChecker`
- move to legacy fact generation module
This commit is contained in:
Rémy Rakic 2024-12-11 12:58:49 +00:00
parent 0894fb0fbf
commit 2fd443888e
4 changed files with 120 additions and 104 deletions

View file

@ -0,0 +1,106 @@
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Place};
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use tracing::debug;
use crate::def_use::{self, DefUse};
use crate::facts::AllFacts;
use crate::location::{LocationIndex, LocationTable};
use crate::universal_regions::UniversalRegions;
type VarPointRelation = Vec<(Local, LocationIndex)>;
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
/// Emit polonius facts for variable defs, uses, drops, and path accesses.
pub(crate) fn emit_access_facts<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
universal_regions: &UniversalRegions<'tcx>,
location_table: &LocationTable,
all_facts: &mut Option<AllFacts>,
) {
if let Some(facts) = all_facts.as_mut() {
debug!("emit_access_facts()");
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
let mut extractor = AccessFactsExtractor {
var_defined_at: &mut facts.var_defined_at,
var_used_at: &mut facts.var_used_at,
var_dropped_at: &mut facts.var_dropped_at,
path_accessed_at_base: &mut facts.path_accessed_at_base,
location_table,
move_data,
};
extractor.visit_body(body);
for (local, local_decl) in body.local_decls.iter_enumerated() {
debug!(
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
local, local_decl.ty
);
tcx.for_each_free_region(&local_decl.ty, |region| {
let region_vid = universal_regions.to_region_vid(region);
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
});
}
}
}
/// MIR visitor extracting point-wise facts about accesses.
struct AccessFactsExtractor<'a, 'tcx> {
var_defined_at: &'a mut VarPointRelation,
var_used_at: &'a mut VarPointRelation,
location_table: &'a LocationTable,
var_dropped_at: &'a mut VarPointRelation,
move_data: &'a MoveData<'tcx>,
path_accessed_at_base: &'a mut PathPointRelation,
}
impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
fn location_to_index(&self, location: Location) -> LocationIndex {
self.location_table.mid_index(location)
}
}
impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
match def_use::categorize(context) {
Some(DefUse::Def) => {
debug!("AccessFactsExtractor - emit def");
self.var_defined_at.push((local, self.location_to_index(location)));
}
Some(DefUse::Use) => {
debug!("AccessFactsExtractor - emit use");
self.var_used_at.push((local, self.location_to_index(location)));
}
Some(DefUse::Drop) => {
debug!("AccessFactsExtractor - emit drop");
self.var_dropped_at.push((local, self.location_to_index(location)));
}
_ => (),
}
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
self.super_place(place, context, location);
match context {
PlaceContext::NonMutatingUse(_)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
_ => {
// There's no path access to emit.
return;
}
};
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
self.path_accessed_at_base.push((path, self.location_to_index(location)));
}
_ => {}
}
}
}

View file

@ -13,9 +13,12 @@ use crate::facts::{AllFacts, PoloniusRegionVid};
use crate::location::LocationTable;
use crate::type_check::free_region_relations::UniversalRegionRelations;
mod accesses;
mod loan_invalidations;
mod loan_kills;
pub(crate) use accesses::emit_access_facts;
/// When requested, emit most of the facts needed by polonius:
/// - moves and assignments
/// - universal regions and their relations

View file

@ -45,7 +45,14 @@ pub(super) fn generate<'a, 'tcx>(
let (relevant_live_locals, boring_locals) =
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
polonius::emit_access_facts(typeck, body, move_data);
crate::polonius::legacy::emit_access_facts(
typeck.tcx(),
body,
move_data,
typeck.universal_regions,
typeck.location_table,
typeck.all_facts,
);
trace::trace(
typeck,

View file

@ -1,54 +1,11 @@
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Place};
use rustc_middle::mir::Local;
use rustc_middle::ty::GenericArg;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use tracing::debug;
use super::TypeChecker;
use crate::def_use::{self, DefUse};
use crate::location::{LocationIndex, LocationTable};
type VarPointRelation = Vec<(Local, LocationIndex)>;
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
/// Emit polonius facts for variable defs, uses, drops, and path accesses.
pub(super) fn emit_access_facts<'a, 'tcx>(
typeck: &mut TypeChecker<'a, 'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
) {
if let Some(facts) = typeck.all_facts.as_mut() {
debug!("emit_access_facts()");
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
let location_table = typeck.location_table;
let mut extractor = AccessFactsExtractor {
var_defined_at: &mut facts.var_defined_at,
var_used_at: &mut facts.var_used_at,
var_dropped_at: &mut facts.var_dropped_at,
path_accessed_at_base: &mut facts.path_accessed_at_base,
location_table,
move_data,
};
extractor.visit_body(body);
for (local, local_decl) in body.local_decls.iter_enumerated() {
debug!(
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
local, local_decl.ty
);
let universal_regions = &typeck.universal_regions;
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
let region_vid = universal_regions.to_region_vid(region);
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
});
}
}
}
use crate::type_check::TypeChecker;
/// For every potentially drop()-touched region `region` in `local`'s type
/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
/// (`kind`), emit a Polonius `drop_of_var_derefs_origin(local, origin)` fact.
pub(super) fn emit_drop_facts<'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
local: Local,
@ -64,60 +21,3 @@ pub(super) fn emit_drop_facts<'tcx>(
});
}
}
/// MIR visitor extracting point-wise facts about accesses.
struct AccessFactsExtractor<'a, 'tcx> {
var_defined_at: &'a mut VarPointRelation,
var_used_at: &'a mut VarPointRelation,
location_table: &'a LocationTable,
var_dropped_at: &'a mut VarPointRelation,
move_data: &'a MoveData<'tcx>,
path_accessed_at_base: &'a mut PathPointRelation,
}
impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
fn location_to_index(&self, location: Location) -> LocationIndex {
self.location_table.mid_index(location)
}
}
impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
match def_use::categorize(context) {
Some(DefUse::Def) => {
debug!("AccessFactsExtractor - emit def");
self.var_defined_at.push((local, self.location_to_index(location)));
}
Some(DefUse::Use) => {
debug!("AccessFactsExtractor - emit use");
self.var_used_at.push((local, self.location_to_index(location)));
}
Some(DefUse::Drop) => {
debug!("AccessFactsExtractor - emit drop");
self.var_dropped_at.push((local, self.location_to_index(location)));
}
_ => (),
}
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
self.super_place(place, context, location);
match context {
PlaceContext::NonMutatingUse(_)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
_ => {
// There's no path access to emit.
return;
}
};
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
self.path_accessed_at_base.push((path, self.location_to_index(location)));
}
_ => {}
}
}
}