]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / nll / type_check / liveness / polonius.rs
CommitLineData
416331ca 1use crate::borrow_check::location::{LocationIndex, LocationTable};
e1599b0c
XL
2use crate::dataflow::indexes::MovePathIndex;
3use crate::dataflow::move_paths::{LookupResult, MoveData};
416331ca 4use crate::util::liveness::{categorize, DefUse};
e1599b0c
XL
5use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
6use rustc::mir::{Body, Local, Location, Place};
e74abb32 7use rustc::ty::subst::GenericArg;
416331ca
XL
8use rustc::ty::Ty;
9
10use super::TypeChecker;
11
12type VarPointRelations = Vec<(Local, LocationIndex)>;
e1599b0c 13type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>;
416331ca 14
e1599b0c 15struct UseFactsExtractor<'me> {
416331ca
XL
16 var_defined: &'me mut VarPointRelations,
17 var_used: &'me mut VarPointRelations,
18 location_table: &'me LocationTable,
e74abb32 19 var_drop_used: &'me mut Vec<(Local, Location)>,
e1599b0c
XL
20 move_data: &'me MoveData<'me>,
21 path_accessed_at: &'me mut MovePathPointRelations,
416331ca
XL
22}
23
24// A Visitor to walk through the MIR and extract point-wise facts
e1599b0c 25impl UseFactsExtractor<'_> {
416331ca
XL
26 fn location_to_index(&self, location: Location) -> LocationIndex {
27 self.location_table.mid_index(location)
28 }
29
30 fn insert_def(&mut self, local: Local, location: Location) {
31 debug!("LivenessFactsExtractor::insert_def()");
32 self.var_defined.push((local, self.location_to_index(location)));
33 }
34
35 fn insert_use(&mut self, local: Local, location: Location) {
36 debug!("LivenessFactsExtractor::insert_use()");
37 self.var_used.push((local, self.location_to_index(location)));
38 }
e1599b0c
XL
39
40 fn insert_drop_use(&mut self, local: Local, location: Location) {
41 debug!("LivenessFactsExtractor::insert_drop_use()");
e74abb32 42 self.var_drop_used.push((local, location));
e1599b0c
XL
43 }
44
45 fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
46 debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location);
47 self.path_accessed_at.push((path, self.location_to_index(location)));
48 }
49
50 fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
51 match self.move_data.rev_lookup.find(place.as_ref()) {
52 LookupResult::Exact(mpi) => Some(mpi),
53 LookupResult::Parent(mmpi) => mmpi,
54 }
55 }
416331ca
XL
56}
57
e1599b0c 58impl Visitor<'tcx> for UseFactsExtractor<'_> {
416331ca
XL
59 fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
60 match categorize(context) {
61 Some(DefUse::Def) => self.insert_def(local, location),
62 Some(DefUse::Use) => self.insert_use(local, location),
e1599b0c
XL
63 Some(DefUse::Drop) => self.insert_drop_use(local, location),
64 _ => (),
65 }
66 }
67
68 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
69 self.super_place(place, context, location);
70 match context {
71 PlaceContext::NonMutatingUse(_) => {
72 if let Some(mpi) = self.place_to_mpi(place) {
73 self.insert_path_access(mpi, location);
74 }
75 }
76
77 PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
78 if let Some(mpi) = self.place_to_mpi(place) {
79 self.insert_path_access(mpi, location);
80 }
81 }
416331ca 82 _ => (),
416331ca
XL
83 }
84 }
85}
86
87fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) {
88 debug!("add_regions(local={:?}, type={:?})", local, ty);
89 typeck.tcx().for_each_free_region(&ty, |region| {
90 let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(region);
91 debug!("add_regions for region {:?}", region_vid);
92 if let Some(facts) = typeck.borrowck_context.all_facts {
93 facts.var_uses_region.push((local, region_vid));
94 }
95 });
96}
97
e1599b0c 98pub(super) fn populate_access_facts(
416331ca 99 typeck: &mut TypeChecker<'_, 'tcx>,
e1599b0c 100 body: &Body<'tcx>,
416331ca 101 location_table: &LocationTable,
e1599b0c 102 move_data: &MoveData<'_>,
e74abb32 103 drop_used: &mut Vec<(Local, Location)>,
416331ca
XL
104) {
105 debug!("populate_var_liveness_facts()");
106
107 if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
e1599b0c 108 UseFactsExtractor {
416331ca
XL
109 var_defined: &mut facts.var_defined,
110 var_used: &mut facts.var_used,
e74abb32 111 var_drop_used: drop_used,
e1599b0c 112 path_accessed_at: &mut facts.path_accessed_at,
416331ca 113 location_table,
e1599b0c 114 move_data,
416331ca 115 }
e1599b0c 116 .visit_body(body);
e74abb32
XL
117
118 facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| {
119 (local, location_table.mid_index(location))
120 }));
416331ca
XL
121 }
122
e1599b0c 123 for (local, local_decl) in body.local_decls.iter_enumerated() {
416331ca
XL
124 add_var_uses_regions(typeck, local, local_decl.ty);
125 }
126}
127
128// For every potentially drop()-touched region `region` in `local`'s type
129// (`kind`), emit a Polonius `var_drops_region(local, region)` fact.
130pub(super) fn add_var_drops_regions(
131 typeck: &mut TypeChecker<'_, 'tcx>,
132 local: Local,
e74abb32 133 kind: &GenericArg<'tcx>,
416331ca
XL
134) {
135 debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind);
136 let tcx = typeck.tcx();
137
138 tcx.for_each_free_region(kind, |drop_live_region| {
139 let region_vid = typeck.borrowck_context.universal_regions.to_region_vid(drop_live_region);
140 if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
141 facts.var_drops_region.push((local, region_vid));
142 };
143 });
144}