@@ -46,13 +46,89 @@ mod reverse_sccs;
4646
4747pub ( crate ) mod values;
4848
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+ }
50126
51127/// The representative region variable for an SCC, tagged by its origin.
52128/// We prefer placeholders over existentially quantified variables, otherwise
53129/// it's the one with the smallest Region Variable ID.
54130#[ derive( Copy , Debug , Clone , PartialEq , PartialOrd , Eq , Ord ) ]
55- enum Representative {
131+ pub enum Representative {
56132 FreeRegion ( RegionVid ) ,
57133 Placeholder ( RegionVid ) ,
58134 Existential ( RegionVid ) ,
@@ -66,6 +142,14 @@ impl Representative {
66142 Representative :: Existential ( region_vid) => * region_vid,
67143 }
68144 }
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+ }
69153}
70154
71155impl scc:: Annotation for Representative {
@@ -457,7 +541,10 @@ pub(crate) enum ExtraConstraintInfo {
457541}
458542
459543#[ 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+ ) {
461548 use crate :: renumber:: RegionCtxt ;
462549
463550 let var_to_origin = infcx. reg_var_to_origin . borrow ( ) ;
@@ -544,27 +631,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
544631 debug ! ( "type tests: {:#?}" , type_tests) ;
545632
546633 // 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+ }
552644
553645 // Add external names from universal regions in fun function definitions.
554646 for ( external_name, variable) in universal_regions. named_universal_regions ( ) {
555647 debug ! ( "region {:?} has external name {:?}" , variable, external_name) ;
556648 definitions[ variable] . external_name = Some ( external_name) ;
557649 }
558- definitions
650+ ( definitions, has_placeholders )
559651 } ;
560652
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+ } ;
563662 let constraints = Frozen :: freeze ( outlives_constraints) ;
564663 let constraint_graph = Frozen :: freeze ( constraints. graph ( definitions. len ( ) ) ) ;
565664
566665 if cfg ! ( debug_assertions) {
567- sccs_info ( infcx, & constraint_sccs) ;
666+ sccs_info ( infcx, & constraint_sccs)
568667 }
569668
570669 let mut scc_values = RegionValues :: new ( elements, universal_regions. len ( ) ) ;
0 commit comments