@@ -75,7 +75,7 @@ pub struct RegionTracker {
75
75
max_universe_placeholder_reached : ReachablePlaceholder ,
76
76
77
77
/// The smallest universe index reachable form the nodes of this SCC.
78
- min_reachable_universe : UniverseIndex ,
78
+ min_reachable_universe : ( UniverseIndex , RegionVid ) ,
79
79
80
80
/// The representative Region Variable Id for this SCC. We prefer
81
81
/// placeholders over existentially quantified variables, otherwise
@@ -86,10 +86,10 @@ pub struct RegionTracker {
86
86
representative_origin : RepresentativeOrigin ,
87
87
88
88
/// The smallest reachable placeholder from this SCC (including in it).
89
- min_reachable_placeholder : Option < RegionVid > ,
89
+ pub ( crate ) min_reachable_placeholder : Option < RegionVid > ,
90
90
91
91
/// The largest reachable placeholder from this SCC (including in it).
92
- max_reachable_placeholder : Option < RegionVid > ,
92
+ pub ( crate ) max_reachable_placeholder : Option < RegionVid > ,
93
93
94
94
/// Is there at least one placeholder in this SCC?
95
95
contains_placeholder : bool ,
@@ -142,7 +142,7 @@ impl RegionTracker {
142
142
143
143
Self {
144
144
max_universe_placeholder_reached,
145
- min_reachable_universe : definition. universe ,
145
+ min_reachable_universe : ( definition. universe , rvid ) ,
146
146
representative : rvid,
147
147
representative_origin,
148
148
min_reachable_placeholder : representative_if_placeholder,
@@ -151,24 +151,6 @@ impl RegionTracker {
151
151
}
152
152
}
153
153
154
- /// Return true if this SCC contains a placeholder that
155
- /// reaches another placeholder, through other SCCs or within
156
- /// it.
157
- fn placeholder_reaches_placeholder ( & self ) -> bool {
158
- // If min and max are different then at least two placeholders
159
- // must be reachable from us. It remains to determine if and
160
- // whose problem that is.
161
- //
162
- // If we are not a placeholder
163
- // we are seeing upstream placeholders, which may be fine, or
164
- // if it is a problem it's the problem for other placeholders.
165
- //
166
- // If we *are* a placeholder, we are reaching at least one other
167
- // placeholder upstream.
168
- self . contains_placeholder
169
- && self . min_reachable_placeholder != self . max_reachable_placeholder
170
- }
171
-
172
154
/// If the representative is a placeholder, return it,
173
155
/// otherwise return None.
174
156
fn placeholder_representative ( & self ) -> Option < RegionVid > {
@@ -181,7 +163,7 @@ impl RegionTracker {
181
163
182
164
/// The smallest-indexed universe reachable from and/or in this SCC.
183
165
fn min_universe ( self ) -> UniverseIndex {
184
- self . min_reachable_universe
166
+ self . min_reachable_universe . 0
185
167
}
186
168
187
169
fn merge_reachable_placeholders ( & mut self , other : & Self ) {
@@ -215,58 +197,37 @@ impl RegionTracker {
215
197
std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
216
198
}
217
199
218
- /// Returns an offending region if the annotated SCC reaches a placeholder
219
- /// with a universe larger than the smallest reachable one,
220
- /// or if a placeholder reaches another placeholder, `None` otherwise.
221
- pub ( crate ) fn placeholder_violation (
222
- & self ,
223
- sccs : & Sccs < RegionVid , ConstraintSccIndex , Self > ,
224
- ) -> Option < RegionVid > {
225
- // Note: we arbitrarily prefer universe violations
226
- // to placeholder-reaches-placeholder violations.
227
- // violations.
228
-
229
- // Case 1: a universe violation
230
- if let ReachablePlaceholder :: Placeholder {
200
+ /// Figure out if there is a universe violation going on.
201
+ /// This can happen in two cases: either one of our placeholders
202
+ /// had its universe lowered from reaching a region with a lower universe,
203
+ /// (in which case we blame the lower universe's region), or because we reached
204
+ /// a larger universe (in which case we blame the larger universe's region).
205
+ pub ( crate ) fn universe_violation ( & self ) -> Option < RegionVid > {
206
+ let ReachablePlaceholder :: Placeholder {
231
207
universe : max_reached_universe,
232
- rvid : belonging_to_rvid ,
208
+ rvid : large_u_rvid ,
233
209
} = self . max_universe_placeholder_reached
234
- {
235
- if self . min_universe ( ) . cannot_name ( max_reached_universe) {
236
- return Some ( belonging_to_rvid) ;
237
- }
238
- }
239
-
240
- // Case 2: a placeholder (in our SCC) reaches another placeholder
241
- if self . placeholder_reaches_placeholder ( ) {
242
- // We know that this SCC contains at least one placeholder
243
- // and that at least two placeholders are reachable from
244
- // this SCC.
245
- //
246
- // We try to pick one that isn't in our SCC, if possible.
247
- // We *always* pick one that is not equal to the representative.
248
-
249
- // Unwrap safety: we know both these values are Some, since
250
- // there are two reachable placeholders at least.
251
- let min_reachable = self . min_reachable_placeholder . unwrap ( ) ;
210
+ else {
211
+ return None ;
212
+ } ;
252
213
253
- if sccs . scc ( min_reachable ) != sccs . scc ( self . representative ) {
254
- return Some ( min_reachable ) ;
255
- }
214
+ if ! self . min_universe ( ) . cannot_name ( max_reached_universe ) {
215
+ return None ;
216
+ } ;
256
217
257
- // Either the largest reachable placeholder is outside our SCC,
258
- // or we *must* blame a placeholder in our SCC since the violation
259
- // happens inside of it. It's slightly easier to always arbitrarily
260
- // pick the largest one, so we do. This also nicely guarantees that
261
- // we don't pick the representative, since the representative is the
262
- // smallest placeholder by index in the SCC if it is a placeholder
263
- // so in order for it to also be the largest reachable min would
264
- // have to be equal to max, but then we would only have reached one
265
- // placeholder .
266
- return Some ( self . max_reachable_placeholder . unwrap ( ) ) ;
267
- }
218
+ debug ! ( "Universe {max_reached_universe:?} is too large for its SCC!" ) ;
219
+ // We originally had a large enough universe to fit all our reachable
220
+ // placeholders, but had it lowered because we also reached something
221
+ // small-universed. In this case, that's to blame!
222
+ let to_blame = if self . representative == large_u_rvid {
223
+ debug ! ( "{:?} lowered our universe!" , self . min_reachable_universe ) ;
224
+ self . min_reachable_universe . 1
225
+ } else {
226
+ // The problem is that we, who have a small universe, reach a large one .
227
+ large_u_rvid
228
+ } ;
268
229
269
- None
230
+ Some ( to_blame )
270
231
}
271
232
}
272
233
@@ -1948,14 +1909,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1948
1909
// relation, redirect the search to the placeholder to blame.
1949
1910
if self . is_static ( to) {
1950
1911
for constraint in path. iter ( ) {
1951
- let ConstraintCategory :: IllegalPlaceholder ( culprit_r) = constraint. category else {
1912
+ let ConstraintCategory :: IllegalPlaceholder ( culprit_from, culprit_to) =
1913
+ constraint. category
1914
+ else {
1952
1915
continue ;
1953
1916
} ;
1954
1917
1955
- debug ! ( "{culprit_r :?} is the reason {from:?}: 'static!" ) ;
1918
+ debug ! ( "{culprit_from:?}: {culprit_to :?} is the reason {from:?}: 'static!" ) ;
1956
1919
// FIXME: think: this may be for transitive reasons and
1957
1920
// we may have to do this arbitrarily many times. Or may we?
1958
- return self . find_constraint_path_to ( from, |r| r == culprit_r, false ) . unwrap ( ) ;
1921
+ return self
1922
+ . find_constraint_path_to ( culprit_from, |r| r == culprit_to, false )
1923
+ . unwrap ( ) ;
1959
1924
}
1960
1925
}
1961
1926
// No funny business; just return the path!
0 commit comments