1
1
#![ deny( rustc:: untranslatable_diagnostic) ]
2
2
#![ deny( rustc:: diagnostic_outside_of_impl) ]
3
- use rustc_infer:: infer:: InferCtxt ;
4
- use rustc_middle:: mir:: visit:: TyContext ;
5
- use rustc_middle:: mir:: visit:: Visitor ;
6
- use rustc_middle:: mir:: {
7
- Body , Local , Location , Place , PlaceRef , ProjectionElem , Rvalue , SourceInfo , Statement ,
8
- StatementKind , Terminator , TerminatorKind , UserTypeProjection ,
9
- } ;
3
+ use rustc_middle:: mir:: visit:: { TyContext , Visitor } ;
4
+ use rustc_middle:: mir:: { Body , Location , SourceInfo } ;
10
5
use rustc_middle:: ty:: visit:: TypeVisitable ;
11
- use rustc_middle:: ty:: GenericArgsRef ;
12
- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
6
+ use rustc_middle:: ty:: { GenericArgsRef , Region , Ty , TyCtxt } ;
13
7
14
- use crate :: {
15
- borrow_set:: BorrowSet , facts:: AllFacts , location:: LocationTable , places_conflict,
16
- region_infer:: values:: LivenessValues ,
17
- } ;
8
+ use crate :: region_infer:: values:: LivenessValues ;
18
9
19
10
pub ( super ) fn generate_constraints < ' tcx > (
20
- infcx : & InferCtxt < ' tcx > ,
11
+ tcx : TyCtxt < ' tcx > ,
21
12
liveness_constraints : & mut LivenessValues ,
22
- all_facts : & mut Option < AllFacts > ,
23
- location_table : & LocationTable ,
24
13
body : & Body < ' tcx > ,
25
- borrow_set : & BorrowSet < ' tcx > ,
26
14
) {
27
- let mut cg = ConstraintGeneration {
28
- borrow_set,
29
- infcx,
30
- liveness_constraints,
31
- location_table,
32
- all_facts,
33
- body,
34
- } ;
35
-
15
+ let mut cg = ConstraintGeneration { tcx, liveness_constraints } ;
36
16
for ( bb, data) in body. basic_blocks . iter_enumerated ( ) {
37
17
cg. visit_basic_block_data ( bb, data) ;
38
18
}
39
19
}
40
20
41
21
/// 'cg = the duration of the constraint generation process itself.
42
22
struct ConstraintGeneration < ' cg , ' tcx > {
43
- infcx : & ' cg InferCtxt < ' tcx > ,
44
- all_facts : & ' cg mut Option < AllFacts > ,
45
- location_table : & ' cg LocationTable ,
23
+ tcx : TyCtxt < ' tcx > ,
46
24
liveness_constraints : & ' cg mut LivenessValues ,
47
- borrow_set : & ' cg BorrowSet < ' tcx > ,
48
- body : & ' cg Body < ' tcx > ,
49
25
}
50
26
51
27
impl < ' cg , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' tcx > {
52
28
/// We sometimes have `args` within an rvalue, or within a
53
29
/// call. Make them live at the location where they appear.
54
30
fn visit_args ( & mut self , args : & GenericArgsRef < ' tcx > , location : Location ) {
55
- self . add_regular_live_constraint ( * args, location) ;
31
+ self . record_regions_live_at ( * args, location) ;
56
32
self . super_args ( args) ;
57
33
}
58
34
59
- /// We sometimes have `region` within an rvalue, or within a
35
+ /// We sometimes have `region`s within an rvalue, or within a
60
36
/// call. Make them live at the location where they appear.
61
- fn visit_region ( & mut self , region : ty :: Region < ' tcx > , location : Location ) {
62
- self . add_regular_live_constraint ( region, location) ;
37
+ fn visit_region ( & mut self , region : Region < ' tcx > , location : Location ) {
38
+ self . record_regions_live_at ( region, location) ;
63
39
self . super_region ( region) ;
64
40
}
65
41
66
- /// We sometimes have `ty` within an rvalue, or within a
42
+ /// We sometimes have `ty`s within an rvalue, or within a
67
43
/// call. Make them live at the location where they appear.
68
44
fn visit_ty ( & mut self , ty : Ty < ' tcx > , ty_context : TyContext ) {
69
45
match ty_context {
@@ -74,175 +50,25 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
74
50
span_bug ! ( span, "should not be visiting outside of the CFG: {:?}" , ty_context) ;
75
51
}
76
52
TyContext :: Location ( location) => {
77
- self . add_regular_live_constraint ( ty, location) ;
53
+ self . record_regions_live_at ( ty, location) ;
78
54
}
79
55
}
80
56
81
57
self . super_ty ( ty) ;
82
58
}
83
-
84
- fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
85
- if let Some ( all_facts) = self . all_facts {
86
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
87
- all_facts. cfg_edge . push ( (
88
- self . location_table . start_index ( location) ,
89
- self . location_table . mid_index ( location) ,
90
- ) ) ;
91
-
92
- all_facts. cfg_edge . push ( (
93
- self . location_table . mid_index ( location) ,
94
- self . location_table . start_index ( location. successor_within_block ( ) ) ,
95
- ) ) ;
96
-
97
- // If there are borrows on this now dead local, we need to record them as `killed`.
98
- if let StatementKind :: StorageDead ( local) = statement. kind {
99
- record_killed_borrows_for_local (
100
- all_facts,
101
- self . borrow_set ,
102
- self . location_table ,
103
- local,
104
- location,
105
- ) ;
106
- }
107
- }
108
-
109
- self . super_statement ( statement, location) ;
110
- }
111
-
112
- fn visit_assign ( & mut self , place : & Place < ' tcx > , rvalue : & Rvalue < ' tcx > , location : Location ) {
113
- // When we see `X = ...`, then kill borrows of
114
- // `(*X).foo` and so forth.
115
- self . record_killed_borrows_for_place ( * place, location) ;
116
-
117
- self . super_assign ( place, rvalue, location) ;
118
- }
119
-
120
- fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
121
- if let Some ( all_facts) = self . all_facts {
122
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
123
- all_facts. cfg_edge . push ( (
124
- self . location_table . start_index ( location) ,
125
- self . location_table . mid_index ( location) ,
126
- ) ) ;
127
-
128
- let successor_blocks = terminator. successors ( ) ;
129
- all_facts. cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
130
- for successor_block in successor_blocks {
131
- all_facts. cfg_edge . push ( (
132
- self . location_table . mid_index ( location) ,
133
- self . location_table . start_index ( successor_block. start_location ( ) ) ,
134
- ) ) ;
135
- }
136
- }
137
-
138
- // A `Call` terminator's return value can be a local which has borrows,
139
- // so we need to record those as `killed` as well.
140
- if let TerminatorKind :: Call { destination, .. } = terminator. kind {
141
- self . record_killed_borrows_for_place ( destination, location) ;
142
- }
143
-
144
- self . super_terminator ( terminator, location) ;
145
- }
146
-
147
- fn visit_ascribe_user_ty (
148
- & mut self ,
149
- _place : & Place < ' tcx > ,
150
- _variance : ty:: Variance ,
151
- _user_ty : & UserTypeProjection ,
152
- _location : Location ,
153
- ) {
154
- }
155
59
}
156
60
157
61
impl < ' cx , ' tcx > ConstraintGeneration < ' cx , ' tcx > {
158
- /// Some variable with type `live_ty` is "regular live" at
159
- /// `location` -- i.e., it may be used later. This means that all
160
- /// regions appearing in the type `live_ty` must be live at
161
- /// `location`.
162
- fn add_regular_live_constraint < T > ( & mut self , live_ty : T , location : Location )
62
+ /// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
63
+ /// all regions appearing in the type of `value` must be live at `location`.
64
+ fn record_regions_live_at < T > ( & mut self , value : T , location : Location )
163
65
where
164
66
T : TypeVisitable < TyCtxt < ' tcx > > ,
165
67
{
166
- debug ! ( "add_regular_live_constraint(live_ty={:?}, location={:?})" , live_ty, location) ;
167
-
168
- self . infcx . tcx . for_each_free_region ( & live_ty, |live_region| {
169
- let vid = live_region. as_var ( ) ;
170
- self . liveness_constraints . add_location ( vid, location) ;
68
+ debug ! ( "add_regular_live_constraint(value={:?}, location={:?})" , value, location) ;
69
+ self . tcx . for_each_free_region ( & value, |live_region| {
70
+ let live_region_vid = live_region. as_var ( ) ;
71
+ self . liveness_constraints . add_location ( live_region_vid, location) ;
171
72
} ) ;
172
73
}
173
-
174
- /// When recording facts for Polonius, records the borrows on the specified place
175
- /// as `killed`. For example, when assigning to a local, or on a call's return destination.
176
- fn record_killed_borrows_for_place ( & mut self , place : Place < ' tcx > , location : Location ) {
177
- if let Some ( all_facts) = self . all_facts {
178
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
179
-
180
- // Depending on the `Place` we're killing:
181
- // - if it's a local, or a single deref of a local,
182
- // we kill all the borrows on the local.
183
- // - if it's a deeper projection, we have to filter which
184
- // of the borrows are killed: the ones whose `borrowed_place`
185
- // conflicts with the `place`.
186
- match place. as_ref ( ) {
187
- PlaceRef { local, projection : & [ ] }
188
- | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
189
- debug ! (
190
- "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
191
- local, location
192
- ) ;
193
-
194
- record_killed_borrows_for_local (
195
- all_facts,
196
- self . borrow_set ,
197
- self . location_table ,
198
- local,
199
- location,
200
- ) ;
201
- }
202
-
203
- PlaceRef { local, projection : & [ .., _] } => {
204
- // Kill conflicting borrows of the innermost local.
205
- debug ! (
206
- "Recording `killed` facts for borrows of \
207
- innermost projected local={:?} at location={:?}",
208
- local, location
209
- ) ;
210
-
211
- if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
212
- for & borrow_index in borrow_indices {
213
- let places_conflict = places_conflict:: places_conflict (
214
- self . infcx . tcx ,
215
- self . body ,
216
- self . borrow_set [ borrow_index] . borrowed_place ,
217
- place,
218
- places_conflict:: PlaceConflictBias :: NoOverlap ,
219
- ) ;
220
-
221
- if places_conflict {
222
- let location_index = self . location_table . mid_index ( location) ;
223
- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
224
- }
225
- }
226
- }
227
- }
228
- }
229
- }
230
- }
231
- }
232
-
233
- /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
234
- fn record_killed_borrows_for_local (
235
- all_facts : & mut AllFacts ,
236
- borrow_set : & BorrowSet < ' _ > ,
237
- location_table : & LocationTable ,
238
- local : Local ,
239
- location : Location ,
240
- ) {
241
- if let Some ( borrow_indices) = borrow_set. local_map . get ( & local) {
242
- all_facts. loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
243
- for & borrow_index in borrow_indices {
244
- let location_index = location_table. mid_index ( location) ;
245
- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
246
- }
247
- }
248
74
}
0 commit comments