blob: 20d7ec55e3e84f0330bd9af69b5ad15f8854b493 [file] [log] [blame]
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Body, Local, Location};
use rustc::ty::subst::Kind;
use rustc::ty::Ty;
use super::TypeChecker;
type VarPointRelations = Vec<(Local, LocationIndex)>;
struct LivenessPointFactsExtractor<'me> {
var_defined: &'me mut VarPointRelations,
var_used: &'me mut VarPointRelations,
location_table: &'me LocationTable,
}
// A Visitor to walk through the MIR and extract point-wise facts
impl LivenessPointFactsExtractor<'_> {
fn location_to_index(&self, location: Location) -> LocationIndex {
self.location_table.mid_index(location)
}
fn insert_def(&mut self, local: Local, location: Location) {
debug!("LivenessFactsExtractor::insert_def()");
self.var_defined.push((local, self.location_to_index(location)));
}
fn insert_use(&mut self, local: Local, location: Location) {
debug!("LivenessFactsExtractor::insert_use()");
self.var_used.push((local, self.location_to_index(location)));
}
}
impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
match categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location),
Some(DefUse::Use) => self.insert_use(local, location),
_ => (),
// NOTE: Drop handling is now done in trace()
}
}
}
fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) {
debug!("add_regions(local={:?}, type={:?})", local, ty);
typeck.tcx().for_each_free_region(&ty, |region| {
let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(region);
debug!("add_regions for region {:?}", region_vid);
if let Some(facts) = typeck.borrowck_context.all_facts {
facts.var_uses_region.push((local, region_vid));
}
});
}
pub(super) fn populate_var_liveness_facts(
typeck: &mut TypeChecker<'_, 'tcx>,
mir: &Body<'tcx>,
location_table: &LocationTable,
) {
debug!("populate_var_liveness_facts()");
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
LivenessPointFactsExtractor {
var_defined: &mut facts.var_defined,
var_used: &mut facts.var_used,
location_table,
}
.visit_body(mir);
}
for (local, local_decl) in mir.local_decls.iter_enumerated() {
add_var_uses_regions(typeck, local, local_decl.ty);
}
}
// For every potentially drop()-touched region `region` in `local`'s type
// (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
pub(super) fn add_var_drops_regions(
typeck: &mut TypeChecker<'_, 'tcx>,
local: Local,
kind: &Kind<'tcx>,
) {
debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
let tcx = typeck.tcx();
tcx.for_each_free_region(kind, |drop_live_region| {
let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(drop_live_region);
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
facts.var_drops_region.push((local, region_vid));
};
});
}