]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | use crate::borrow_check::location::{LocationIndex, LocationTable}; |
e1599b0c XL |
2 | use crate::dataflow::indexes::MovePathIndex; |
3 | use crate::dataflow::move_paths::{LookupResult, MoveData}; | |
416331ca | 4 | use crate::util::liveness::{categorize, DefUse}; |
e1599b0c XL |
5 | use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; |
6 | use rustc::mir::{Body, Local, Location, Place}; | |
e74abb32 | 7 | use rustc::ty::subst::GenericArg; |
416331ca XL |
8 | use rustc::ty::Ty; |
9 | ||
10 | use super::TypeChecker; | |
11 | ||
12 | type VarPointRelations = Vec<(Local, LocationIndex)>; | |
e1599b0c | 13 | type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>; |
416331ca | 14 | |
e1599b0c | 15 | struct 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 | 25 | impl 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 | 58 | impl 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 | ||
87 | fn 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 | 98 | pub(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. | |
130 | pub(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 | } |