@@ -19,15 +19,15 @@ use rustc::mir::{ClosureOutlivesRequirement, ClosureRegionRequirements, Location
19
19
use rustc:: ty:: { self , RegionVid } ;
20
20
use rustc_data_structures:: indexed_vec:: IndexVec ;
21
21
use rustc_data_structures:: fx:: FxHashSet ;
22
- use rustc_data_structures:: bitvec:: BitMatrix ;
23
- use rustc_data_structures:: indexed_vec:: Idx ;
24
- use std:: collections:: BTreeMap ;
25
22
use std:: fmt;
23
+ use std:: rc:: Rc ;
26
24
use syntax_pos:: Span ;
27
25
28
26
mod annotation;
29
27
mod dump_mir;
30
28
mod graphviz;
29
+ mod values;
30
+ use self :: values:: { RegionValueElements , RegionValues } ;
31
31
32
32
pub struct RegionInferenceContext < ' tcx > {
33
33
/// Contains the definition for every region variable. Region
@@ -36,27 +36,22 @@ pub struct RegionInferenceContext<'tcx> {
36
36
/// from as well as its final inferred value.
37
37
definitions : IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
38
38
39
+ /// Maps from points/universal-regions to a `RegionElementIndex`.
40
+ elements : Rc < RegionValueElements > ,
41
+
39
42
/// The liveness constraints added to each region. For most
40
43
/// regions, these start out empty and steadily grow, though for
41
44
/// each universally quantified region R they start out containing
42
45
/// the entire CFG and `end(R)`.
43
- ///
44
- /// In this `BitMatrix` representation, the rows are the region
45
- /// variables and the columns are the free regions and MIR locations.
46
- liveness_constraints : BitMatrix ,
46
+ liveness_constraints : RegionValues ,
47
47
48
48
/// The final inferred values of the inference variables; `None`
49
49
/// until `solve` is invoked.
50
- inferred_values : Option < BitMatrix > ,
50
+ inferred_values : Option < RegionValues > ,
51
51
52
52
/// The constraints we have accumulated and used during solving.
53
53
constraints : Vec < Constraint > ,
54
54
55
- /// A map from each MIR Location to its column index in
56
- /// `liveness_constraints`/`inferred_values`. (The first N columns are
57
- /// the free regions.)
58
- point_indices : BTreeMap < Location , usize > ,
59
-
60
55
/// Information about the universally quantified regions in scope
61
56
/// on this function and their (known) relations to one another.
62
57
universal_regions : UniversalRegions < ' tcx > ,
@@ -112,19 +107,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
112
107
let num_region_variables = var_origins. len ( ) ;
113
108
let num_universal_regions = universal_regions. len ( ) ;
114
109
115
- let mut num_points = 0 ;
116
- let mut point_indices = BTreeMap :: new ( ) ;
117
-
110
+ let mut points = Vec :: new ( ) ;
118
111
for ( block, block_data) in mir. basic_blocks ( ) . iter_enumerated ( ) {
119
112
for statement_index in 0 ..block_data. statements . len ( ) + 1 {
120
- let location = Location {
113
+ points . push ( Location {
121
114
block,
122
115
statement_index,
123
- } ;
124
- point_indices. insert ( location, num_universal_regions + num_points) ;
125
- num_points += 1 ;
116
+ } ) ;
126
117
}
127
118
}
119
+ let elements = & Rc :: new ( RegionValueElements :: new ( points, num_universal_regions) ) ;
128
120
129
121
// Create a RegionDefinition for each inference variable.
130
122
let definitions = var_origins
@@ -134,13 +126,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
134
126
135
127
let mut result = Self {
136
128
definitions,
137
- liveness_constraints : BitMatrix :: new (
138
- num_region_variables,
139
- num_universal_regions + num_points,
140
- ) ,
129
+ elements : elements. clone ( ) ,
130
+ liveness_constraints : RegionValues :: new ( elements, num_region_variables) ,
141
131
inferred_values : None ,
142
132
constraints : Vec :: new ( ) ,
143
- point_indices,
144
133
universal_regions,
145
134
} ;
146
135
@@ -186,14 +175,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
186
175
self . definitions [ variable] . is_universal = true ;
187
176
188
177
// Add all nodes in the CFG to liveness constraints
189
- for ( _location, point_index) in & self . point_indices {
190
- self . liveness_constraints
191
- . add ( variable. index ( ) , * point_index) ;
178
+ for point_index in self . elements . all_point_indices ( ) {
179
+ self . liveness_constraints . add ( variable, point_index) ;
192
180
}
193
181
194
182
// Add `end(X)` into the set for X.
195
- self . liveness_constraints
196
- . add ( variable. index ( ) , variable. index ( ) ) ;
183
+ self . liveness_constraints . add ( variable, variable) ;
197
184
}
198
185
}
199
186
@@ -217,32 +204,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
217
204
let inferred_values = self . inferred_values
218
205
. as_ref ( )
219
206
. expect ( "region values not yet inferred" ) ;
220
- self . region_contains_point_in_matrix ( inferred_values, r, p)
221
- }
222
-
223
- /// True if given region `r` contains the point `p`, when
224
- /// evaluated in the set of region values `matrix`.
225
- fn region_contains_point_in_matrix (
226
- & self ,
227
- matrix : & BitMatrix ,
228
- r : RegionVid ,
229
- p : Location ,
230
- ) -> bool {
231
- let point_index = self . point_indices
232
- . get ( & p)
233
- . expect ( "point index should be known" ) ;
234
- matrix. contains ( r. index ( ) , * point_index)
235
- }
236
-
237
- /// True if given region `r` contains the `end(s)`, when
238
- /// evaluated in the set of region values `matrix`.
239
- fn region_contains_region_in_matrix (
240
- & self ,
241
- matrix : & BitMatrix ,
242
- r : RegionVid ,
243
- s : RegionVid ,
244
- ) -> bool {
245
- matrix. contains ( r. index ( ) , s. index ( ) )
207
+ inferred_values. contains ( r, p)
246
208
}
247
209
248
210
/// Returns access to the value of `r` for debugging purposes.
@@ -251,43 +213,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
251
213
. as_ref ( )
252
214
. expect ( "region values not yet inferred" ) ;
253
215
254
- self . region_value_str_from_matrix ( inferred_values, r)
255
- }
256
-
257
- fn region_value_str_from_matrix ( & self ,
258
- matrix : & BitMatrix ,
259
- r : RegionVid ) -> String {
260
- let mut result = String :: new ( ) ;
261
- result. push_str ( "{" ) ;
262
- let mut sep = "" ;
263
-
264
- for & point in self . point_indices . keys ( ) {
265
- if self . region_contains_point_in_matrix ( matrix, r, point) {
266
- result. push_str ( & format ! ( "{}{:?}" , sep, point) ) ;
267
- sep = ", " ;
268
- }
269
- }
270
-
271
- for fr in ( 0 ..self . universal_regions . len ( ) ) . map ( RegionVid :: new) {
272
- if self . region_contains_region_in_matrix ( matrix, r, fr) {
273
- result. push_str ( & format ! ( "{}{:?}" , sep, fr) ) ;
274
- sep = ", " ;
275
- }
276
- }
277
-
278
- result. push_str ( "}" ) ;
279
-
280
- result
216
+ inferred_values. region_value_str ( r)
281
217
}
282
218
283
219
/// Indicates that the region variable `v` is live at the point `point`.
284
220
pub ( super ) fn add_live_point ( & mut self , v : RegionVid , point : Location ) -> bool {
285
221
debug ! ( "add_live_point({:?}, {:?})" , v, point) ;
286
222
assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
287
- let point_index = self . point_indices
288
- . get ( & point)
289
- . expect ( "point index should be known" ) ;
290
- self . liveness_constraints . add ( v. index ( ) , * point_index)
223
+ debug ! ( "add_live_point: @{:?}" , point) ;
224
+
225
+ let element = self . elements . index ( point) ;
226
+ if self . liveness_constraints . add ( v, element) {
227
+ true
228
+ } else {
229
+ false
230
+ }
291
231
}
292
232
293
233
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
@@ -386,16 +326,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
386
326
outlives_requirements : & mut Vec < ClosureOutlivesRequirement > ,
387
327
) {
388
328
let inferred_values = self . inferred_values . as_ref ( ) . unwrap ( ) ;
389
- let longer_value = inferred_values. iter ( longer_fr. index ( ) ) ;
390
329
391
330
debug ! ( "check_universal_region(fr={:?})" , longer_fr) ;
392
331
393
332
// Find every region `o` such that `fr: o`
394
333
// (because `fr` includes `end(o)`).
395
- let shorter_frs = longer_value
396
- . take_while ( |& i| i < self . universal_regions . len ( ) )
397
- . map ( RegionVid :: new) ;
398
- for shorter_fr in shorter_frs {
334
+ for shorter_fr in inferred_values. universal_regions_outlived_by ( longer_fr) {
399
335
// If it is known that `fr: o`, carry on.
400
336
if self . universal_regions . outlives ( longer_fr, shorter_fr) {
401
337
continue ;
@@ -512,20 +448,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
512
448
513
449
fn copy (
514
450
& self ,
515
- inferred_values : & mut BitMatrix ,
451
+ inferred_values : & mut RegionValues ,
516
452
mir : & Mir < ' tcx > ,
517
453
from_region : RegionVid ,
518
454
to_region : RegionVid ,
519
- start_point : Location ,
455
+ constraint_point : Location ,
520
456
) -> bool {
521
457
let mut changed = false ;
522
458
523
459
let mut stack = vec ! [ ] ;
524
460
let mut visited = FxHashSet ( ) ;
525
461
526
- stack. push ( start_point ) ;
462
+ stack. push ( constraint_point ) ;
527
463
while let Some ( p) = stack. pop ( ) {
528
- if !self . region_contains_point_in_matrix ( inferred_values, from_region, p) {
464
+ let point_index = self . elements . index ( p) ;
465
+
466
+ if !inferred_values. contains ( from_region, point_index) {
529
467
debug ! ( " not in from-region" ) ;
530
468
continue ;
531
469
}
@@ -535,8 +473,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
535
473
continue ;
536
474
}
537
475
538
- let point_index = self . point_indices . get ( & p ) . unwrap ( ) ;
539
- changed |= inferred_values . add ( to_region . index ( ) , * point_index ) ;
476
+ let new = inferred_values . add ( to_region , point_index ) ;
477
+ changed |= new ;
540
478
541
479
let block_data = & mir[ p. block ] ;
542
480
let successor_points = if p. statement_index < block_data. statements . len ( ) {
@@ -564,13 +502,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
564
502
// If we reach the END point in the graph, then copy
565
503
// over any skolemized end points in the `from_region`
566
504
// and make sure they are included in the `to_region`.
567
- let universal_region_indices = inferred_values
568
- . iter ( from_region. index ( ) )
569
- . take_while ( |& i| i < self . universal_regions . len ( ) )
570
- . collect :: < Vec < _ > > ( ) ;
571
- for fr in & universal_region_indices {
572
- changed |= inferred_values. add ( to_region. index ( ) , * fr) ;
573
- }
505
+ changed |=
506
+ inferred_values. add_universal_regions_outlived_by ( from_region, to_region) ;
574
507
} else {
575
508
stack. extend ( successor_points) ;
576
509
}
0 commit comments