@@ -46,13 +46,89 @@ mod reverse_sccs;
46
46
47
47
pub ( crate ) mod values;
48
48
49
- pub ( crate ) type ConstraintSccs = Sccs < RegionVid , ConstraintSccIndex , RegionTracker > ;
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 ) ,
55
+ }
56
+
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
+ }
76
+ }
77
+ }
78
+
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
+ }
94
+ }
95
+
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
+ }
101
+ }
102
+
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
+ }
108
+ }
109
+
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
+ }
117
+ }
118
+
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
+ }
125
+ }
50
126
51
127
/// The representative region variable for an SCC, tagged by its origin.
52
128
/// We prefer placeholders over existentially quantified variables, otherwise
53
129
/// it's the one with the smallest Region Variable ID.
54
130
#[ derive( Copy , Debug , Clone , PartialEq , PartialOrd , Eq , Ord ) ]
55
- enum Representative {
131
+ pub enum Representative {
56
132
FreeRegion ( RegionVid ) ,
57
133
Placeholder ( RegionVid ) ,
58
134
Existential ( RegionVid ) ,
@@ -66,6 +142,14 @@ impl Representative {
66
142
Representative :: Existential ( region_vid) => * region_vid,
67
143
}
68
144
}
145
+
146
+ fn new ( r : RegionVid , definitions : & IndexVec < RegionVid , RegionDefinition < ' _ > > ) -> Self {
147
+ match definitions[ r] . origin {
148
+ NllRegionVariableOrigin :: FreeRegion => Representative :: FreeRegion ( r) ,
149
+ NllRegionVariableOrigin :: Placeholder ( _) => Representative :: Placeholder ( r) ,
150
+ NllRegionVariableOrigin :: Existential { .. } => Representative :: Existential ( r) ,
151
+ }
152
+ }
69
153
}
70
154
71
155
impl scc:: Annotation for Representative {
@@ -457,7 +541,10 @@ pub(crate) enum ExtraConstraintInfo {
457
541
}
458
542
459
543
#[ instrument( skip( infcx, sccs) , level = "debug" ) ]
460
- fn sccs_info < ' tcx > ( infcx : & BorrowckInferCtxt < ' tcx > , sccs : & ConstraintSccs ) {
544
+ fn sccs_info < ' tcx , A : scc:: Annotation > (
545
+ infcx : & BorrowckInferCtxt < ' tcx > ,
546
+ sccs : & scc:: Sccs < RegionVid , ConstraintSccIndex , A > ,
547
+ ) {
461
548
use crate :: renumber:: RegionCtxt ;
462
549
463
550
let var_to_origin = infcx. reg_var_to_origin . borrow ( ) ;
@@ -544,27 +631,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
544
631
debug ! ( "type tests: {:#?}" , type_tests) ;
545
632
546
633
// Create a RegionDefinition for each inference variable.
547
- let definitions = {
548
- let mut definitions: IndexVec < _ , _ > = var_infos
549
- . iter ( )
550
- . map ( |info| RegionDefinition :: new ( info. universe , info. origin ) )
551
- . collect ( ) ;
634
+ let ( definitions, has_placeholders) = {
635
+ let mut definitions = IndexVec :: with_capacity ( var_infos. len ( ) ) ;
636
+ let mut has_placeholders = false ;
637
+
638
+ for info in var_infos. iter ( ) {
639
+ let definition = RegionDefinition :: new ( info. universe , info. origin ) ;
640
+ has_placeholders |=
641
+ matches ! ( definition. origin, NllRegionVariableOrigin :: Placeholder ( _) ) ;
642
+ definitions. push ( definition) ;
643
+ }
552
644
553
645
// Add external names from universal regions in fun function definitions.
554
646
for ( external_name, variable) in universal_regions. named_universal_regions ( ) {
555
647
debug ! ( "region {:?} has external name {:?}" , variable, external_name) ;
556
648
definitions[ variable] . external_name = Some ( external_name) ;
557
649
}
558
- definitions
650
+ ( definitions, has_placeholders )
559
651
} ;
560
652
561
- let constraint_sccs =
562
- outlives_constraints. add_outlives_static ( & universal_regions, & definitions) ;
653
+ let constraint_sccs = if has_placeholders {
654
+ debug ! ( "Placeholders present; activating placeholder handling logic!" ) ;
655
+ outlives_constraints. add_outlives_static ( & universal_regions, & definitions)
656
+ } else {
657
+ 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
+ } )
661
+ } ;
563
662
let constraints = Frozen :: freeze ( outlives_constraints) ;
564
663
let constraint_graph = Frozen :: freeze ( constraints. graph ( definitions. len ( ) ) ) ;
565
664
566
665
if cfg ! ( debug_assertions) {
567
- sccs_info ( infcx, & constraint_sccs) ;
666
+ sccs_info ( infcx, & constraint_sccs)
568
667
}
569
668
570
669
let mut scc_values = RegionValues :: new ( elements, universal_regions. len ( ) ) ;
0 commit comments