@@ -4,6 +4,7 @@ use std::rc::Rc;
44use rustc_data_structures:: binary_search_util;
55use rustc_data_structures:: frozen:: Frozen ;
66use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
7+ use rustc_data_structures:: graph:: scc:: { self , Sccs } ;
78use rustc_errors:: Diag ;
89use rustc_hir:: def_id:: CRATE_DEF_ID ;
910use rustc_index:: IndexVec ;
@@ -23,7 +24,6 @@ use rustc_mir_dataflow::points::DenseLocationMap;
2324use rustc_span:: Span ;
2425
2526use crate :: constraints:: graph:: { self , NormalConstraintGraph , RegionGraph } ;
26- use crate :: constraints:: { ConstraintSccs , RegionTracker } ;
2727use crate :: dataflow:: BorrowIndex ;
2828use crate :: {
2929 constraints:: { ConstraintSccIndex , OutlivesConstraint , OutlivesConstraintSet } ,
@@ -46,6 +46,97 @@ mod reverse_sccs;
4646
4747pub mod values;
4848
49+ pub type ConstraintSccs = Sccs < RegionVid , ConstraintSccIndex , RegionTracker > ;
50+
51+ /// An annotation for region graph SCCs that tracks
52+ /// the values of its elements.
53+ #[ derive( Copy , Debug , Clone ) ]
54+ pub struct RegionTracker {
55+ /// The largest universe of a placeholder reached from this SCC.
56+ /// This includes placeholders within this SCC.
57+ max_placeholder_universe_reached : UniverseIndex ,
58+
59+ /// The smallest universe index reachable form the nodes of this SCC.
60+ min_reachable_universe : UniverseIndex ,
61+
62+ /// The representative Region Variable Id for this SCC. We prefer
63+ /// placeholders over existentially quantified variables, otherwise
64+ /// it's the one with the smallest Region Variable ID.
65+ representative : RegionVid ,
66+
67+ /// Is the current representative a placeholder?
68+ representative_is_placeholder : bool ,
69+
70+ /// Is the current representative existentially quantified?
71+ representative_is_existential : bool ,
72+ }
73+
74+ impl scc:: Annotation for RegionTracker {
75+ fn merge_scc ( mut self , mut other : Self ) -> Self {
76+ // Prefer any placeholder over any existential
77+ if other. representative_is_placeholder && self . representative_is_existential {
78+ other. merge_min_max_seen ( & self ) ;
79+ return other;
80+ }
81+
82+ if self . representative_is_placeholder && other. representative_is_existential
83+ || ( self . representative <= other. representative )
84+ {
85+ self . merge_min_max_seen ( & other) ;
86+ return self ;
87+ }
88+ other. merge_min_max_seen ( & self ) ;
89+ other
90+ }
91+
92+ fn merge_reached ( mut self , other : Self ) -> Self {
93+ // No update to in-component values, only add seen values.
94+ self . merge_min_max_seen ( & other) ;
95+ self
96+ }
97+ }
98+
99+ impl RegionTracker {
100+ fn new ( rvid : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
101+ let ( representative_is_placeholder, representative_is_existential) = match definition. origin
102+ {
103+ rustc_infer:: infer:: NllRegionVariableOrigin :: FreeRegion => ( false , false ) ,
104+ rustc_infer:: infer:: NllRegionVariableOrigin :: Placeholder ( _) => ( true , false ) ,
105+ rustc_infer:: infer:: NllRegionVariableOrigin :: Existential { .. } => ( false , true ) ,
106+ } ;
107+
108+ let placeholder_universe =
109+ if representative_is_placeholder { definition. universe } else { UniverseIndex :: ROOT } ;
110+
111+ Self {
112+ max_placeholder_universe_reached : placeholder_universe,
113+ min_reachable_universe : definition. universe ,
114+ representative : rvid,
115+ representative_is_placeholder,
116+ representative_is_existential,
117+ }
118+ }
119+ fn universe ( self ) -> UniverseIndex {
120+ self . min_reachable_universe
121+ }
122+
123+ fn merge_min_max_seen ( & mut self , other : & Self ) {
124+ self . max_placeholder_universe_reached = std:: cmp:: max (
125+ self . max_placeholder_universe_reached ,
126+ other. max_placeholder_universe_reached ,
127+ ) ;
128+
129+ self . min_reachable_universe =
130+ std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
131+ }
132+
133+ /// Returns `true` if during the annotated SCC reaches a placeholder
134+ /// with a universe larger than the smallest reachable one, `false` otherwise.
135+ pub fn has_incompatible_universes ( & self ) -> bool {
136+ self . universe ( ) . cannot_name ( self . max_placeholder_universe_reached )
137+ }
138+ }
139+
49140pub struct RegionInferenceContext < ' tcx > {
50141 pub var_infos : VarInfos ,
51142
0 commit comments