]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
Remove in_band_lifetimes from borrowck
[rust.git] / compiler / rustc_borrowck / src / type_check / liveness / polonius.rs
1 use crate::def_use::{self, DefUse};
2 use crate::location::{LocationIndex, LocationTable};
3 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
4 use rustc_middle::mir::{Body, Local, Location, Place};
5 use rustc_middle::ty::subst::GenericArg;
6 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
7
8 use super::TypeChecker;
9
10 type VarPointRelation = Vec<(Local, LocationIndex)>;
11 type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
12
13 struct UseFactsExtractor<'me> {
14     var_defined_at: &'me mut VarPointRelation,
15     var_used_at: &'me mut VarPointRelation,
16     location_table: &'me LocationTable,
17     var_dropped_at: &'me mut VarPointRelation,
18     move_data: &'me MoveData<'me>,
19     path_accessed_at_base: &'me mut PathPointRelation,
20 }
21
22 // A Visitor to walk through the MIR and extract point-wise facts
23 impl UseFactsExtractor<'_> {
24     fn location_to_index(&self, location: Location) -> LocationIndex {
25         self.location_table.mid_index(location)
26     }
27
28     fn insert_def(&mut self, local: Local, location: Location) {
29         debug!("UseFactsExtractor::insert_def()");
30         self.var_defined_at.push((local, self.location_to_index(location)));
31     }
32
33     fn insert_use(&mut self, local: Local, location: Location) {
34         debug!("UseFactsExtractor::insert_use()");
35         self.var_used_at.push((local, self.location_to_index(location)));
36     }
37
38     fn insert_drop_use(&mut self, local: Local, location: Location) {
39         debug!("UseFactsExtractor::insert_drop_use()");
40         self.var_dropped_at.push((local, self.location_to_index(location)));
41     }
42
43     fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
44         debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
45         self.path_accessed_at_base.push((path, self.location_to_index(location)));
46     }
47
48     fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
49         match self.move_data.rev_lookup.find(place.as_ref()) {
50             LookupResult::Exact(mpi) => Some(mpi),
51             LookupResult::Parent(mmpi) => mmpi,
52         }
53     }
54 }
55
56 impl Visitor<'_> for UseFactsExtractor<'_> {
57     fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
58         match def_use::categorize(context) {
59             Some(DefUse::Def) => self.insert_def(local, location),
60             Some(DefUse::Use) => self.insert_use(local, location),
61             Some(DefUse::Drop) => self.insert_drop_use(local, location),
62             _ => (),
63         }
64     }
65
66     fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) {
67         self.super_place(place, context, location);
68         match context {
69             PlaceContext::NonMutatingUse(_) => {
70                 if let Some(mpi) = self.place_to_mpi(place) {
71                     self.insert_path_access(mpi, location);
72                 }
73             }
74
75             PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
76                 if let Some(mpi) = self.place_to_mpi(place) {
77                     self.insert_path_access(mpi, location);
78                 }
79             }
80             _ => (),
81         }
82     }
83 }
84
85 pub(super) fn populate_access_facts<'tcx>(
86     typeck: &mut TypeChecker<'_, 'tcx>,
87     body: &Body<'tcx>,
88     location_table: &LocationTable,
89     move_data: &MoveData<'_>,
90     dropped_at: &mut Vec<(Local, Location)>,
91 ) {
92     debug!("populate_access_facts()");
93
94     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
95         let mut extractor = UseFactsExtractor {
96             var_defined_at: &mut facts.var_defined_at,
97             var_used_at: &mut facts.var_used_at,
98             var_dropped_at: &mut facts.var_dropped_at,
99             path_accessed_at_base: &mut facts.path_accessed_at_base,
100             location_table,
101             move_data,
102         };
103         extractor.visit_body(&body);
104
105         facts.var_dropped_at.extend(
106             dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))),
107         );
108
109         for (local, local_decl) in body.local_decls.iter_enumerated() {
110             debug!(
111                 "add use_of_var_derefs_origin facts - local={:?}, type={:?}",
112                 local, local_decl.ty
113             );
114             let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
115             let universal_regions = &typeck.borrowck_context.universal_regions;
116             typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
117                 let region_vid = universal_regions.to_region_vid(region);
118                 facts.use_of_var_derefs_origin.push((local, region_vid));
119             });
120         }
121     }
122 }
123
124 // For every potentially drop()-touched region `region` in `local`'s type
125 // (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
126 pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
127     typeck: &mut TypeChecker<'_, 'tcx>,
128     local: Local,
129     kind: &GenericArg<'tcx>,
130 ) {
131     debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
132     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
133         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
134         let universal_regions = &typeck.borrowck_context.universal_regions;
135         typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
136             let region_vid = universal_regions.to_region_vid(drop_live_region);
137             facts.drop_of_var_derefs_origin.push((local, region_vid));
138         });
139     }
140 }