@@ -4,6 +4,7 @@ use std::rc::Rc;
4
4
use rustc_data_structures:: binary_search_util;
5
5
use rustc_data_structures:: frozen:: Frozen ;
6
6
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
7
+ use rustc_data_structures:: graph:: scc:: { self , Sccs } ;
7
8
use rustc_errors:: Diag ;
8
9
use rustc_hir:: def_id:: CRATE_DEF_ID ;
9
10
use rustc_index:: IndexVec ;
@@ -23,7 +24,6 @@ use rustc_mir_dataflow::points::DenseLocationMap;
23
24
use rustc_span:: Span ;
24
25
25
26
use crate :: constraints:: graph:: { self , NormalConstraintGraph , RegionGraph } ;
26
- use crate :: constraints:: { ConstraintSccs , RegionTracker } ;
27
27
use crate :: dataflow:: BorrowIndex ;
28
28
use crate :: {
29
29
constraints:: { ConstraintSccIndex , OutlivesConstraint , OutlivesConstraintSet } ,
@@ -46,6 +46,97 @@ mod reverse_sccs;
46
46
47
47
pub mod values;
48
48
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
+
49
140
pub struct RegionInferenceContext < ' tcx > {
50
141
pub var_infos : VarInfos ,
51
142
0 commit comments