+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));
+ };
+ });
+}