@@ -28,6 +28,16 @@ pub struct RegionInferenceContext<'tcx> {
28
28
/// from as well as its final inferred value.
29
29
definitions : IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
30
30
31
+ /// The liveness constraints added to each region. For most
32
+ /// regions, these start out empty and steadily grow, though for
33
+ /// each free region R they start out containing the entire CFG
34
+ /// and `end(R)`.
35
+ liveness_constraints : IndexVec < RegionVid , Region > ,
36
+
37
+ /// The final inferred values of the inference variables; `None`
38
+ /// until `solve` is invoked.
39
+ inferred_values : Option < IndexVec < RegionVid , Region > > ,
40
+
31
41
/// The constraints we have accumulated and used during solving.
32
42
constraints : Vec < Constraint > ,
33
43
}
@@ -46,11 +56,6 @@ struct RegionDefinition<'tcx> {
46
56
/// If true, this is a constant region which cannot grow larger.
47
57
/// This is used for named regions as well as `'static`.
48
58
constant : bool ,
49
-
50
- /// The current value of this inference variable. This starts out
51
- /// empty, but grows as we add constraints. The final value is
52
- /// determined when `solve()` is executed.
53
- value : Region ,
54
59
}
55
60
56
61
/// The value of an individual region variable. Region variables
@@ -115,6 +120,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
115
120
/// of those will be constant regions representing the free
116
121
/// regions defined in `free_regions`.
117
122
pub fn new ( var_origins : VarOrigins , free_regions : & FreeRegions < ' tcx > , mir : & Mir < ' tcx > ) -> Self {
123
+ let num_region_variables = var_origins. len ( ) ;
124
+
118
125
// Create a RegionDefinition for each inference variable.
119
126
let definitions = var_origins
120
127
. into_iter ( )
@@ -123,6 +130,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
123
130
124
131
let mut result = Self {
125
132
definitions : definitions,
133
+ liveness_constraints : IndexVec :: from_elem_n ( Region :: default ( ) , num_region_variables) ,
134
+ inferred_values : None ,
126
135
constraints : Vec :: new ( ) ,
127
136
} ;
128
137
@@ -170,24 +179,23 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
170
179
171
180
// Add all nodes in the CFG to `definition.value`.
172
181
for ( block, block_data) in mir. basic_blocks ( ) . iter_enumerated ( ) {
173
- let definition = & mut self . definitions [ variable] ;
182
+ let liveness_constraint = & mut self . liveness_constraints [ variable] ;
174
183
for statement_index in 0 ..block_data. statements . len ( ) + 1 {
175
184
let location = Location {
176
185
block,
177
186
statement_index,
178
187
} ;
179
- definition . value . add_point ( location) ;
188
+ liveness_constraint . add_point ( location) ;
180
189
}
181
190
}
182
191
183
192
// Add `end(X)` into the set for X.
184
- self . definitions [ variable] . value . add_free_region ( variable) ;
193
+ self . liveness_constraints [ variable] . add_free_region ( variable) ;
185
194
186
195
// `'static` outlives all other free regions as well.
187
196
if let ty:: ReStatic = free_region {
188
197
for & other_variable in indices. values ( ) {
189
- self . definitions [ variable]
190
- . value
198
+ self . liveness_constraints [ variable]
191
199
. add_free_region ( other_variable) ;
192
200
}
193
201
}
@@ -196,16 +204,14 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
196
204
// Y: X is true). Add `end(X)` into the set for `Y`.
197
205
for superregion in free_region_map. regions_that_outlive ( & free_region) {
198
206
let superregion_index = indices[ superregion] ;
199
- self . definitions [ superregion_index]
200
- . value
201
- . add_free_region ( variable) ;
207
+ self . liveness_constraints [ superregion_index] . add_free_region ( variable) ;
202
208
}
203
209
204
210
debug ! (
205
211
"init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`" ,
206
212
free_region,
207
213
variable,
208
- self . definitions [ variable] . value
214
+ self . liveness_constraints [ variable] ,
209
215
) ;
210
216
}
211
217
}
@@ -219,25 +225,25 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
219
225
///
220
226
/// Until `solve()` executes, this value is not particularly meaningful.
221
227
pub fn region_contains_point ( & self , r : RegionVid , p : Location ) -> bool {
222
- self . definitions [ r] . value . contains_point ( p)
228
+ let inferred_values = self . inferred_values
229
+ . as_ref ( )
230
+ . expect ( "region values not yet inferred" ) ;
231
+ inferred_values[ r] . contains_point ( p)
223
232
}
224
233
225
234
/// Returns access to the value of `r` for debugging purposes.
226
235
pub ( super ) fn region_value ( & self , r : RegionVid ) -> & fmt:: Debug {
227
- & self . definitions [ r] . value
236
+ let inferred_values = self . inferred_values
237
+ . as_ref ( )
238
+ . expect ( "region values not yet inferred" ) ;
239
+ & inferred_values[ r]
228
240
}
229
241
230
242
/// Indicates that the region variable `v` is live at the point `point`.
231
243
pub ( super ) fn add_live_point ( & mut self , v : RegionVid , point : Location ) {
232
244
debug ! ( "add_live_point({:?}, {:?})" , v, point) ;
233
- let definition = & mut self . definitions [ v] ;
234
- if !definition. constant {
235
- definition. value . add_point ( point) ;
236
- } else {
237
- // Constants are used for free regions, which already
238
- // contain all the points in the control-flow graph.
239
- assert ! ( definition. value. contains_point( point) ) ;
240
- }
245
+ assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
246
+ self . liveness_constraints [ v] . add_point ( point) ;
241
247
}
242
248
243
249
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
@@ -249,6 +255,7 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
249
255
point : Location ,
250
256
) {
251
257
debug ! ( "add_outlives({:?}: {:?} @ {:?}" , sup, sub, point) ;
258
+ assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
252
259
self . constraints . push ( Constraint {
253
260
span,
254
261
sup,
@@ -259,6 +266,7 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
259
266
260
267
/// Perform region inference.
261
268
pub ( super ) fn solve ( & mut self , infcx : & InferCtxt < ' a , ' gcx , ' tcx > , mir : & Mir < ' tcx > ) {
269
+ assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
262
270
let errors = self . propagate_constraints ( mir) ;
263
271
264
272
// worst error msg ever
@@ -291,39 +299,43 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
291
299
constraints
292
300
} ) ;
293
301
302
+ // The initial values for each region are derived from the liveness
303
+ // constraints we have accumulated.
304
+ let mut inferred_values = self . liveness_constraints . clone ( ) ;
305
+
294
306
while changed {
295
307
changed = false ;
296
308
for constraint in & self . constraints {
297
309
debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
298
- let sub = & self . definitions [ constraint. sub ] . value . clone ( ) ;
299
- let sup_def = & mut self . definitions [ constraint. sup ] ;
310
+ let sub = & inferred_values [ constraint. sub ] . clone ( ) ;
311
+ let sup_value = & mut inferred_values [ constraint. sup ] ;
300
312
301
313
debug ! ( "propagate_constraints: sub (before): {:?}" , sub) ;
302
- debug ! ( "propagate_constraints: sup (before): {:?}" , sup_def . value ) ;
314
+ debug ! ( "propagate_constraints: sup (before): {:?}" , sup_value ) ;
303
315
304
- if !sup_def . constant {
316
+ if !self . definitions [ constraint . sup ] . constant {
305
317
// If this is not a constant, then grow the value as needed to
306
318
// accommodate the outlives constraint.
307
319
308
- if dfs. copy ( sub, & mut sup_def . value , constraint. point ) {
320
+ if dfs. copy ( sub, sup_value , constraint. point ) {
309
321
changed = true ;
310
322
}
311
323
312
- debug ! ( "propagate_constraints: sup (after) : {:?}" , sup_def . value ) ;
324
+ debug ! ( "propagate_constraints: sup (after) : {:?}" , sup_value ) ;
313
325
debug ! ( "propagate_constraints: changed : {:?}" , changed) ;
314
326
} else {
315
327
// If this is a constant, check whether it *would
316
328
// have* to grow in order for the constraint to be
317
329
// satisfied. If so, create an error.
318
330
319
- let mut sup_value = sup_def . value . clone ( ) ;
320
- if dfs. copy ( sub, & mut sup_value, constraint. point ) {
331
+ let sup_value = & mut sup_value . clone ( ) ;
332
+ if dfs. copy ( sub, sup_value, constraint. point ) {
321
333
// Constant values start out with the entire
322
334
// CFG, so it must be some new free region
323
335
// that was added. Find one.
324
336
let & new_region = sup_value
325
337
. free_regions
326
- . difference ( & sup_def . value . free_regions )
338
+ . difference ( & sup_value . free_regions )
327
339
. next ( )
328
340
. unwrap ( ) ;
329
341
debug ! ( "propagate_constraints: new_region : {:?}" , new_region) ;
@@ -335,6 +347,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
335
347
}
336
348
debug ! ( "\n " ) ;
337
349
}
350
+
351
+ self . inferred_values = Some ( inferred_values) ;
338
352
errors
339
353
}
340
354
}
@@ -424,7 +438,6 @@ impl<'tcx> RegionDefinition<'tcx> {
424
438
origin,
425
439
name : None ,
426
440
constant : false ,
427
- value : Region :: default ( ) ,
428
441
}
429
442
}
430
443
}
0 commit comments