8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use std:: collections:: HashMap ;
12
-
13
11
use super :: universal_regions:: UniversalRegions ;
14
12
use rustc:: hir:: def_id:: DefId ;
15
13
use rustc:: infer:: InferCtxt ;
@@ -23,9 +21,9 @@ use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegi
23
21
Local , Location , Mir } ;
24
22
use rustc:: traits:: ObligationCause ;
25
23
use rustc:: ty:: { self , RegionVid , Ty , TypeFoldable } ;
26
- use rustc:: util:: common:: ErrorReported ;
24
+ use rustc:: util:: common:: { self , ErrorReported } ;
27
25
use rustc_data_structures:: bitvec:: BitVector ;
28
- use rustc_data_structures:: indexed_vec:: IndexVec ;
26
+ use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
29
27
use std:: fmt;
30
28
use std:: rc:: Rc ;
31
29
use syntax:: ast;
@@ -61,8 +59,15 @@ pub struct RegionInferenceContext<'tcx> {
61
59
/// until `solve` is invoked.
62
60
inferred_values : Option < RegionValues > ,
63
61
62
+ /// For each variable, stores the index of the first constraint
63
+ /// where that variable appears on the RHS. This is the start of a
64
+ /// 'linked list' threaded by the `next` field in `Constraint`.
65
+ ///
66
+ /// This map is build when values are inferred.
67
+ dependency_map : Option < IndexVec < RegionVid , Option < ConstraintIndex > > > ,
68
+
64
69
/// The constraints we have accumulated and used during solving.
65
- constraints : Vec < Constraint > ,
70
+ constraints : IndexVec < ConstraintIndex , Constraint > ,
66
71
67
72
/// Type constraints that we check after solving.
68
73
type_tests : Vec < TypeTest < ' tcx > > ,
@@ -143,10 +148,22 @@ pub struct Constraint {
143
148
/// At this location.
144
149
point : Location ,
145
150
151
+ /// Later on, we thread the constraints onto a linked list
152
+ /// sorted by their `sub` field. So if you had:
153
+ ///
154
+ /// Index | Constraint | Next Field
155
+ /// ----- | ---------- | ----------
156
+ /// 0 | `'a: 'b` | Some(2)
157
+ /// 1 | `'b: 'c` | None
158
+ /// 2 | `'c: 'b` | None
159
+ next : Option < ConstraintIndex > ,
160
+
146
161
/// Where did this constraint arise?
147
162
span : Span ,
148
163
}
149
164
165
+ newtype_index ! ( ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" } ) ;
166
+
150
167
/// A "type test" corresponds to an outlives constraint between a type
151
168
/// and a lifetime, like `T: 'x` or `<T as Foo>::Bar: 'x`. They are
152
169
/// translated from the `Verify` region constraints in the ordinary
@@ -259,7 +276,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
259
276
elements : elements. clone ( ) ,
260
277
liveness_constraints : RegionValues :: new ( elements, num_region_variables) ,
261
278
inferred_values : None ,
262
- constraints : Vec :: new ( ) ,
279
+ dependency_map : None ,
280
+ constraints : IndexVec :: new ( ) ,
263
281
type_tests : Vec :: new ( ) ,
264
282
universal_regions,
265
283
} ;
@@ -387,6 +405,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
387
405
sup,
388
406
sub,
389
407
point,
408
+ next : None ,
390
409
} ) ;
391
410
}
392
411
@@ -403,6 +422,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
403
422
infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
404
423
mir : & Mir < ' tcx > ,
405
424
mir_def_id : DefId ,
425
+ ) -> Option < ClosureRegionRequirements < ' gcx > > {
426
+ common:: time ( infcx. tcx . sess , & format ! ( "solve({:?})" , mir_def_id) , || {
427
+ self . solve_inner ( infcx, mir, mir_def_id)
428
+ } )
429
+ }
430
+
431
+ fn solve_inner < ' gcx > (
432
+ & mut self ,
433
+ infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
434
+ mir : & Mir < ' tcx > ,
435
+ mir_def_id : DefId ,
406
436
) -> Option < ClosureRegionRequirements < ' gcx > > {
407
437
assert ! ( self . inferred_values. is_none( ) , "values already inferred" ) ;
408
438
@@ -448,6 +478,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
448
478
/// satisfied. Note that some values may grow **too** large to be
449
479
/// feasible, but we check this later.
450
480
fn propagate_constraints ( & mut self , mir : & Mir < ' tcx > ) {
481
+ self . dependency_map = Some ( self . build_dependency_map ( ) ) ;
451
482
let inferred_values = self . compute_region_values ( mir, TrackCauses ( false ) ) ;
452
483
self . inferred_values = Some ( inferred_values) ;
453
484
}
@@ -465,17 +496,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
465
496
// constraints we have accumulated.
466
497
let mut inferred_values = self . liveness_constraints . duplicate ( track_causes) ;
467
498
468
- let dependency_map = self . build_dependency_map ( ) ;
499
+ let dependency_map = self . dependency_map . as_ref ( ) . unwrap ( ) ;
469
500
470
501
// Constraints that may need to be repropagated (initially all):
471
- let mut dirty_list: Vec < _ > = ( 0 .. self . constraints . len ( ) ) . collect ( ) ;
502
+ let mut dirty_list: Vec < _ > = self . constraints . indices ( ) . collect ( ) ;
472
503
473
504
// Set to 0 for each constraint that is on the dirty list:
474
505
let mut clean_bit_vec = BitVector :: new ( dirty_list. len ( ) ) ;
475
506
476
507
debug ! ( "propagate_constraints: --------------------" ) ;
477
508
while let Some ( constraint_idx) = dirty_list. pop ( ) {
478
- clean_bit_vec. insert ( constraint_idx) ;
509
+ clean_bit_vec. insert ( constraint_idx. index ( ) ) ;
479
510
480
511
let constraint = & self . constraints [ constraint_idx] ;
481
512
debug ! ( "propagate_constraints: constraint={:?}" , constraint) ;
@@ -497,10 +528,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
497
528
debug ! ( "propagate_constraints: sub={:?}" , constraint. sub) ;
498
529
debug ! ( "propagate_constraints: sup={:?}" , constraint. sup) ;
499
530
500
- for & dep_idx in dependency_map. get ( & constraint. sup ) . unwrap_or ( & vec ! [ ] ) {
501
- if clean_bit_vec. remove ( dep_idx) {
531
+ let mut opt_dep_idx = dependency_map[ constraint. sup ] ;
532
+ while let Some ( dep_idx) = opt_dep_idx {
533
+ if clean_bit_vec. remove ( dep_idx. index ( ) ) {
502
534
dirty_list. push ( dep_idx) ;
503
535
}
536
+ opt_dep_idx = self . constraints [ dep_idx] . next ;
504
537
}
505
538
}
506
539
@@ -514,11 +547,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
514
547
/// indices of constraints that need to be re-evaluated when X changes.
515
548
/// These are constraints like Y: X @ P -- so if X changed, we may
516
549
/// need to grow Y.
517
- fn build_dependency_map ( & self ) -> HashMap < RegionVid , Vec < usize > > {
518
- let mut map = HashMap :: new ( ) ;
519
-
520
- for ( idx, constraint) in self . constraints . iter ( ) . enumerate ( ) {
521
- map. entry ( constraint. sub ) . or_insert ( Vec :: new ( ) ) . push ( idx) ;
550
+ #[ inline( never) ]
551
+ fn build_dependency_map ( & mut self ) -> IndexVec < RegionVid , Option < ConstraintIndex > > {
552
+ let mut map = IndexVec :: from_elem ( None , & self . definitions ) ;
553
+
554
+ for ( idx, constraint) in self . constraints . iter_enumerated_mut ( ) . rev ( ) {
555
+ let mut head = & mut map[ constraint. sub ] ;
556
+ debug_assert ! ( constraint. next. is_none( ) ) ;
557
+ constraint. next = * head;
558
+ * head = Some ( idx) ;
522
559
}
523
560
524
561
map
0 commit comments