@@ -46,89 +46,53 @@ mod reverse_sccs;
46
46
47
47
pub ( crate ) mod values;
48
48
49
- pub ( crate ) type ConstraintSccs = Sccs < RegionVid , ConstraintSccIndex , PlaceholderTracking > ;
50
-
51
- #[ derive( Copy , Clone , Debug ) ]
52
- pub enum PlaceholderTracking {
53
- Off ( Representative ) ,
54
- On ( RegionTracker ) ,
49
+ pub ( crate ) struct SccAnnotations < ' d , ' tcx , A : scc:: Annotation > {
50
+ pub ( crate ) scc_to_annotation : IndexVec < ConstraintSccIndex , A > ,
51
+ definitions : & ' d IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
55
52
}
56
53
57
- impl scc:: Annotation for PlaceholderTracking {
58
- fn merge_scc ( self , other : Self ) -> Self {
59
- use PlaceholderTracking :: * ;
60
-
61
- match ( self , other) {
62
- ( Off ( this) , Off ( that) ) => Off ( this. merge_scc ( that) ) ,
63
- ( On ( this) , On ( that) ) => On ( this. merge_scc ( that) ) ,
64
- _ => unreachable ! ( ) ,
65
- }
66
- }
67
-
68
- fn merge_reached ( self , other : Self ) -> Self {
69
- use PlaceholderTracking :: * ;
70
-
71
- match ( self , other) {
72
- ( Off ( this) , Off ( that) ) => Off ( this. merge_reached ( that) ) ,
73
- ( On ( this) , On ( that) ) => On ( this. merge_reached ( that) ) ,
74
- _ => unreachable ! ( ) ,
75
- }
54
+ impl < ' d , ' tcx , A : scc:: Annotation > SccAnnotations < ' d , ' tcx , A > {
55
+ pub ( crate ) fn init ( definitions : & ' d IndexVec < RegionVid , RegionDefinition < ' tcx > > ) -> Self {
56
+ Self { scc_to_annotation : IndexVec :: new ( ) , definitions }
76
57
}
77
58
}
78
59
79
- impl PlaceholderTracking {
80
- pub ( crate ) fn representative_rvid ( & self ) -> RegionVid {
81
- match self {
82
- PlaceholderTracking :: Off ( r) => r. rvid ( ) ,
83
- PlaceholderTracking :: On ( region_tracker) => region_tracker. representative_rvid ( ) ,
84
- }
85
- }
86
-
87
- pub ( crate ) fn reaches_other_placeholder ( & self , other : RegionVid ) -> Option < RegionVid > {
88
- match self {
89
- PlaceholderTracking :: Off ( _) => None ,
90
- PlaceholderTracking :: On ( region_tracker) => {
91
- region_tracker. reaches_other_placeholder ( other)
92
- }
93
- }
60
+ impl scc:: Annotations < RegionVid , ConstraintSccIndex , RegionTracker >
61
+ for SccAnnotations < ' _ , ' _ , RegionTracker >
62
+ {
63
+ fn new ( & self , element : RegionVid ) -> RegionTracker {
64
+ RegionTracker :: new ( element, & self . definitions [ element] )
94
65
}
95
66
96
- pub ( crate ) fn universe_violation ( & self ) -> Option < RegionVid > {
97
- match self {
98
- PlaceholderTracking :: Off ( _) => None ,
99
- PlaceholderTracking :: On ( region_tracker) => region_tracker. universe_violation ( ) ,
100
- }
67
+ fn annotate_scc ( & mut self , scc : ConstraintSccIndex , annotation : RegionTracker ) {
68
+ let idx = self . scc_to_annotation . push ( annotation) ;
69
+ assert ! ( idx == scc) ;
101
70
}
71
+ }
102
72
103
- fn min_universe ( & self ) -> UniverseIndex {
104
- match self {
105
- PlaceholderTracking :: Off ( _ ) => UniverseIndex :: ROOT , // Not technically correct?
106
- PlaceholderTracking :: On ( region_tracker ) => region_tracker . min_universe ( ) ,
107
- }
73
+ impl scc :: Annotations < RegionVid , ConstraintSccIndex , Representative >
74
+ for SccAnnotations < ' _ , ' _ , Representative >
75
+ {
76
+ fn new ( & self , element : RegionVid ) -> Representative {
77
+ Representative :: new ( element , self . definitions )
108
78
}
109
79
110
- fn universe_compatible_with ( & self , other : PlaceholderTracking ) -> bool {
111
- use PlaceholderTracking :: * ;
112
- match ( self , other) {
113
- ( Off ( _) , Off ( _) ) => true , // Not technically correct?
114
- ( On ( this) , On ( that) ) => this. universe_compatible_with ( that) ,
115
- _ => unreachable ! ( ) ,
116
- }
80
+ fn annotate_scc ( & mut self , scc : ConstraintSccIndex , annotation : Representative ) {
81
+ let idx = self . scc_to_annotation . push ( annotation) ;
82
+ assert ! ( idx == scc) ;
117
83
}
84
+ }
118
85
119
- fn placeholder_representative ( & self ) -> Option < RegionVid > {
120
- match self {
121
- PlaceholderTracking :: Off ( _) => None ,
122
- PlaceholderTracking :: On ( region_tracker) => region_tracker. placeholder_representative ( ) ,
123
- }
124
- }
86
+ pub ( crate ) enum PlaceholderTracking {
87
+ Off ( IndexVec < ConstraintSccIndex , Representative > ) ,
88
+ On ( IndexVec < ConstraintSccIndex , RegionTracker > ) ,
125
89
}
126
90
127
91
/// The representative region variable for an SCC, tagged by its origin.
128
92
/// We prefer placeholders over existentially quantified variables, otherwise
129
93
/// it's the one with the smallest Region Variable ID.
130
94
#[ derive( Copy , Debug , Clone , PartialEq , PartialOrd , Eq , Ord ) ]
131
- pub enum Representative {
95
+ pub ( crate ) enum Representative {
132
96
FreeRegion ( RegionVid ) ,
133
97
Placeholder ( RegionVid ) ,
134
98
Existential ( RegionVid ) ,
@@ -217,7 +181,7 @@ impl PlaceholderReachability {
217
181
/// An annotation for region graph SCCs that tracks
218
182
/// the values of its elements.
219
183
#[ derive( Copy , Debug , Clone ) ]
220
- pub struct RegionTracker {
184
+ pub ( crate ) struct RegionTracker {
221
185
/// The representative Region Variable Id for this SCC.
222
186
representative : Representative ,
223
187
@@ -379,7 +343,9 @@ pub struct RegionInferenceContext<'tcx> {
379
343
/// The SCC computed from `constraints` and the constraint
380
344
/// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
381
345
/// compute the values of each region.
382
- constraint_sccs : ConstraintSccs ,
346
+ constraint_sccs : Sccs < RegionVid , ConstraintSccIndex > ,
347
+
348
+ scc_annotations : PlaceholderTracking ,
383
349
384
350
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if
385
351
/// `B: A`. This is used to compute the universal regions that are required
@@ -541,9 +507,9 @@ pub(crate) enum ExtraConstraintInfo {
541
507
}
542
508
543
509
#[ instrument( skip( infcx, sccs) , level = "debug" ) ]
544
- fn sccs_info < ' tcx , A : scc :: Annotation > (
510
+ fn sccs_info < ' tcx > (
545
511
infcx : & BorrowckInferCtxt < ' tcx > ,
546
- sccs : & scc:: Sccs < RegionVid , ConstraintSccIndex , A > ,
512
+ sccs : & scc:: Sccs < RegionVid , ConstraintSccIndex > ,
547
513
) {
548
514
use crate :: renumber:: RegionCtxt ;
549
515
@@ -624,7 +590,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
624
590
universe_causes : FxIndexMap < ty:: UniverseIndex , UniverseInfo < ' tcx > > ,
625
591
type_tests : Vec < TypeTest < ' tcx > > ,
626
592
mut liveness_constraints : LivenessValues ,
627
- elements : & Rc < DenseLocationMap > ,
593
+ elements : Rc < DenseLocationMap > ,
628
594
) -> Self {
629
595
debug ! ( "universal_regions: {:#?}" , universal_regions) ;
630
596
debug ! ( "outlives constraints: {:#?}" , outlives_constraints) ;
@@ -650,14 +616,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
650
616
( definitions, has_placeholders)
651
617
} ;
652
618
653
- let constraint_sccs = if has_placeholders {
619
+ let ( constraint_sccs, scc_annotations ) = if has_placeholders {
654
620
debug ! ( "Placeholders present; activating placeholder handling logic!" ) ;
655
621
outlives_constraints. add_outlives_static ( & universal_regions, & definitions)
656
622
} else {
657
623
debug ! ( "No placeholders in MIR body; disabling their validation." ) ;
658
- outlives_constraints. compute_sccs ( universal_regions. fr_static , & definitions, |r| {
659
- PlaceholderTracking :: Off ( Representative :: new ( r, & definitions) )
660
- } )
624
+ let mut annotator = SccAnnotations :: init ( & definitions) ;
625
+ let sccs = outlives_constraints. compute_sccs (
626
+ universal_regions. fr_static ,
627
+ definitions. len ( ) ,
628
+ & mut annotator,
629
+ ) ;
630
+ ( sccs, PlaceholderTracking :: Off ( annotator. scc_to_annotation ) )
661
631
} ;
662
632
let constraints = Frozen :: freeze ( outlives_constraints) ;
663
633
let constraint_graph = Frozen :: freeze ( constraints. graph ( definitions. len ( ) ) ) ;
@@ -707,6 +677,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
707
677
type_tests,
708
678
universal_regions,
709
679
universal_region_relations,
680
+ scc_annotations,
710
681
}
711
682
}
712
683
@@ -932,8 +903,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
932
903
933
904
// If the member region lives in a higher universe, we currently choose
934
905
// the most conservative option by leaving it unchanged.
935
-
936
- if !self . constraint_sccs ( ) . annotation ( scc) . min_universe ( ) . is_root ( ) {
906
+ if !self . scc_universe ( scc) . is_root ( ) {
937
907
return ;
938
908
}
939
909
@@ -1005,9 +975,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1005
975
/// in `scc_a`. Used during constraint propagation, and only once
1006
976
/// the value of `scc_b` has been computed.
1007
977
fn universe_compatible ( & self , scc_b : ConstraintSccIndex , scc_a : ConstraintSccIndex ) -> bool {
1008
- self . constraint_sccs ( )
1009
- . annotation ( scc_a)
1010
- . universe_compatible_with ( self . constraint_sccs ( ) . annotation ( scc_b) )
978
+ match & self . scc_annotations {
979
+ // This isn't technically true but seems to work.
980
+ PlaceholderTracking :: Off ( _) => true ,
981
+ PlaceholderTracking :: On ( annotations) => {
982
+ annotations[ scc_a] . universe_compatible_with ( annotations[ scc_b] )
983
+ }
984
+ }
1011
985
}
1012
986
1013
987
/// Once regions have been propagated, this method is used to see
@@ -1115,7 +1089,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1115
1089
"lower_bound = {:?} r_scc={:?} universe={:?}" ,
1116
1090
lower_bound,
1117
1091
r_scc,
1118
- self . constraint_sccs . annotation ( r_scc) . min_universe ( )
1092
+ self . scc_universe ( r_scc)
1119
1093
) ;
1120
1094
1121
1095
// If the type test requires that `T: 'a` where `'a` is a
@@ -1125,7 +1099,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1125
1099
// It doesn't matter *what* universe because the promoted `T` will
1126
1100
// always be in the root universe.
1127
1101
1128
- if let Some ( p) = self . constraint_sccs . annotation ( r_scc ) . placeholder_representative ( ) {
1102
+ if let Some ( p) = self . placeholder_representative ( r_scc ) {
1129
1103
debug ! ( "encountered placeholder in higher universe: {:?}, requiring 'static" , p) ;
1130
1104
let static_r = self . universal_regions . fr_static ;
1131
1105
propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
@@ -1633,7 +1607,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1633
1607
/// The minimum universe of any variable reachable from this
1634
1608
/// SCC, inside or outside of it.
1635
1609
fn scc_universe ( & self , scc : ConstraintSccIndex ) -> UniverseIndex {
1636
- self . constraint_sccs ( ) . annotation ( scc) . min_universe ( )
1610
+ match & self . scc_annotations {
1611
+ PlaceholderTracking :: Off ( _) => UniverseIndex :: ROOT , // Not technically correct?
1612
+ PlaceholderTracking :: On ( annotations) => annotations[ scc] . min_universe ( ) ,
1613
+ }
1637
1614
}
1638
1615
/// Checks the final value for the free region `fr` to see if it
1639
1616
/// grew too large. In particular, examine what `end(X)` points
@@ -2303,7 +2280,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
2303
2280
/// This can be used to quickly under-approximate the regions which are equal to each other
2304
2281
/// and their relative orderings.
2305
2282
// This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
2306
- pub fn constraint_sccs ( & self ) -> & ConstraintSccs {
2283
+ pub fn constraint_sccs ( & self ) -> & Sccs < RegionVid , ConstraintSccIndex > {
2307
2284
& self . constraint_sccs
2308
2285
}
2309
2286
@@ -2343,7 +2320,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
2343
2320
/// they *must* be equal (though not having the same repr does not
2344
2321
/// mean they are unequal).
2345
2322
fn scc_representative ( & self , scc : ConstraintSccIndex ) -> RegionVid {
2346
- self . constraint_sccs . annotation ( scc) . representative_rvid ( )
2323
+ match & self . scc_annotations {
2324
+ PlaceholderTracking :: Off ( annotations) => annotations[ scc] . rvid ( ) ,
2325
+ PlaceholderTracking :: On ( annotations) => annotations[ scc] . representative_rvid ( ) ,
2326
+ }
2347
2327
}
2348
2328
2349
2329
/// Returns true if `r` is `'static`.
@@ -2357,13 +2337,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
2357
2337
& self ,
2358
2338
scc : ConstraintSccIndex ,
2359
2339
) -> Option < PlaceholderRegion > {
2360
- if let Some ( representative) =
2361
- self . constraint_sccs . annotation ( scc) . placeholder_representative ( )
2362
- && let NllRegionVariableOrigin :: Placeholder ( p) = self . definitions [ representative] . origin
2363
- {
2364
- Some ( p)
2365
- } else {
2366
- None
2340
+ match & self . scc_annotations {
2341
+ PlaceholderTracking :: Off ( _) => None ,
2342
+ PlaceholderTracking :: On ( annotations) => {
2343
+ if let Some ( representative) = annotations[ scc] . placeholder_representative ( )
2344
+ && let NllRegionVariableOrigin :: Placeholder ( p) =
2345
+ self . definitions [ representative] . origin
2346
+ {
2347
+ Some ( p)
2348
+ } else {
2349
+ None
2350
+ }
2351
+ }
2367
2352
}
2368
2353
}
2369
2354
}
0 commit comments