1 use crate::borrow_check::location::{LocationIndex, LocationTable};
2 use crate::dataflow::indexes::MovePathIndex;
3 use crate::dataflow::move_paths::{LookupResult, MoveData};
4 use crate::util::liveness::{categorize, DefUse};
5 use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
6 use rustc::mir::{Local, Location, Place, ReadOnlyBodyAndCache};
7 use rustc::ty::subst::GenericArg;
9 use super::TypeChecker;
11 type VarPointRelation = Vec<(Local, LocationIndex)>;
12 type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
14 struct UseFactsExtractor<'me> {
15 var_defined: &'me mut VarPointRelation,
16 var_used: &'me mut VarPointRelation,
17 location_table: &'me LocationTable,
18 var_drop_used: &'me mut Vec<(Local, Location)>,
19 move_data: &'me MoveData<'me>,
20 path_accessed_at: &'me mut PathPointRelation,
23 // A Visitor to walk through the MIR and extract point-wise facts
24 impl UseFactsExtractor<'_> {
25 fn location_to_index(&self, location: Location) -> LocationIndex {
26 self.location_table.mid_index(location)
29 fn insert_def(&mut self, local: Local, location: Location) {
30 debug!("UseFactsExtractor::insert_def()");
31 self.var_defined.push((local, self.location_to_index(location)));
34 fn insert_use(&mut self, local: Local, location: Location) {
35 debug!("UseFactsExtractor::insert_use()");
36 self.var_used.push((local, self.location_to_index(location)));
39 fn insert_drop_use(&mut self, local: Local, location: Location) {
40 debug!("UseFactsExtractor::insert_drop_use()");
41 self.var_drop_used.push((local, location));
44 fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
45 debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
46 self.path_accessed_at.push((path, self.location_to_index(location)));
49 fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
50 match self.move_data.rev_lookup.find(place.as_ref()) {
51 LookupResult::Exact(mpi) => Some(mpi),
52 LookupResult::Parent(mmpi) => mmpi,
57 impl Visitor<'tcx> for UseFactsExtractor<'_> {
58 fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
59 match categorize(context) {
60 Some(DefUse::Def) => self.insert_def(local, location),
61 Some(DefUse::Use) => self.insert_use(local, location),
62 Some(DefUse::Drop) => self.insert_drop_use(local, location),
67 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
68 self.super_place(place, context, location);
70 PlaceContext::NonMutatingUse(_) => {
71 if let Some(mpi) = self.place_to_mpi(place) {
72 self.insert_path_access(mpi, location);
76 PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
77 if let Some(mpi) = self.place_to_mpi(place) {
78 self.insert_path_access(mpi, location);
86 pub(super) fn populate_access_facts(
87 typeck: &mut TypeChecker<'_, 'tcx>,
88 body: ReadOnlyBodyAndCache<'_, 'tcx>,
89 location_table: &LocationTable,
90 move_data: &MoveData<'_>,
91 drop_used: &mut Vec<(Local, Location)>,
93 debug!("populate_access_facts()");
95 if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
96 let mut extractor = UseFactsExtractor {
97 var_defined: &mut facts.var_defined,
98 var_used: &mut facts.var_used,
99 var_drop_used: drop_used,
100 path_accessed_at: &mut facts.path_accessed_at,
104 extractor.visit_body(body);
106 facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| {
107 (local, location_table.mid_index(location))
110 for (local, local_decl) in body.local_decls.iter_enumerated() {
111 debug!("add var_uses_regions facts - local={:?}, type={:?}", local, local_decl.ty);
112 let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
113 let universal_regions = &typeck.borrowck_context.universal_regions;
114 typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
115 let region_vid = universal_regions.to_region_vid(region);
116 facts.var_uses_region.push((local, region_vid));
122 // For every potentially drop()-touched region `region` in `local`'s type
123 // (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
124 pub(super) fn add_var_drops_regions(
125 typeck: &mut TypeChecker<'_, 'tcx>,
127 kind: &GenericArg<'tcx>,
129 debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
130 if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
131 let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
132 let universal_regions = &typeck.borrowck_context.universal_regions;
133 typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
134 let region_vid = universal_regions.to_region_vid(drop_live_region);
135 facts.var_drops_region.push((local, region_vid));