@@ -76,7 +76,7 @@ pub struct RegionTracker {
7676 max_universe_placeholder_reached : ReachablePlaceholder ,
7777
7878 /// The smallest universe index reachable form the nodes of this SCC.
79- min_reachable_universe : UniverseIndex ,
79+ min_reachable_universe : ( UniverseIndex , RegionVid ) ,
8080
8181 /// The representative Region Variable Id for this SCC. We prefer
8282 /// placeholders over existentially quantified variables, otherwise
@@ -87,10 +87,10 @@ pub struct RegionTracker {
8787 representative_origin : RepresentativeOrigin ,
8888
8989 /// The smallest reachable placeholder from this SCC (including in it).
90- min_reachable_placeholder : Option < RegionVid > ,
90+ pub ( crate ) min_reachable_placeholder : Option < RegionVid > ,
9191
9292 /// The largest reachable placeholder from this SCC (including in it).
93- max_reachable_placeholder : Option < RegionVid > ,
93+ pub ( crate ) max_reachable_placeholder : Option < RegionVid > ,
9494
9595 /// Is there at least one placeholder in this SCC?
9696 contains_placeholder : bool ,
@@ -143,7 +143,7 @@ impl RegionTracker {
143143
144144 Self {
145145 max_universe_placeholder_reached,
146- min_reachable_universe : definition. universe ,
146+ min_reachable_universe : ( definition. universe , rvid ) ,
147147 representative : rvid,
148148 representative_origin,
149149 min_reachable_placeholder : representative_if_placeholder,
@@ -152,24 +152,6 @@ impl RegionTracker {
152152 }
153153 }
154154
155- /// Return true if this SCC contains a placeholder that
156- /// reaches another placeholder, through other SCCs or within
157- /// it.
158- fn placeholder_reaches_placeholder ( & self ) -> bool {
159- // If min and max are different then at least two placeholders
160- // must be reachable from us. It remains to determine if and
161- // whose problem that is.
162- //
163- // If we are not a placeholder
164- // we are seeing upstream placeholders, which may be fine, or
165- // if it is a problem it's the problem for other placeholders.
166- //
167- // If we *are* a placeholder, we are reaching at least one other
168- // placeholder upstream.
169- self . contains_placeholder
170- && self . min_reachable_placeholder != self . max_reachable_placeholder
171- }
172-
173155 /// If the representative is a placeholder, return it,
174156 /// otherwise return None.
175157 fn placeholder_representative ( & self ) -> Option < RegionVid > {
@@ -182,7 +164,7 @@ impl RegionTracker {
182164
183165 /// The smallest-indexed universe reachable from and/or in this SCC.
184166 fn min_universe ( self ) -> UniverseIndex {
185- self . min_reachable_universe
167+ self . min_reachable_universe . 0
186168 }
187169
188170 fn merge_reachable_placeholders ( & mut self , other : & Self ) {
@@ -216,58 +198,37 @@ impl RegionTracker {
216198 std:: cmp:: min ( self . min_reachable_universe , other. min_reachable_universe ) ;
217199 }
218200
219- /// Returns an offending region if the annotated SCC reaches a placeholder
220- /// with a universe larger than the smallest reachable one,
221- /// or if a placeholder reaches another placeholder, `None` otherwise.
222- pub ( crate ) fn placeholder_violation (
223- & self ,
224- sccs : & Sccs < RegionVid , ConstraintSccIndex , Self > ,
225- ) -> Option < RegionVid > {
226- // Note: we arbitrarily prefer universe violations
227- // to placeholder-reaches-placeholder violations.
228- // violations.
229-
230- // Case 1: a universe violation
231- if let ReachablePlaceholder :: Placeholder {
201+ /// Figure out if there is a universe violation going on.
202+ /// This can happen in two cases: either one of our placeholders
203+ /// had its universe lowered from reaching a region with a lower universe,
204+ /// (in which case we blame the lower universe's region), or because we reached
205+ /// a larger universe (in which case we blame the larger universe's region).
206+ pub ( crate ) fn universe_violation ( & self ) -> Option < RegionVid > {
207+ let ReachablePlaceholder :: Placeholder {
232208 universe : max_reached_universe,
233- rvid : belonging_to_rvid ,
209+ rvid : large_u_rvid ,
234210 } = self . max_universe_placeholder_reached
235- {
236- if self . min_universe ( ) . cannot_name ( max_reached_universe) {
237- return Some ( belonging_to_rvid) ;
238- }
239- }
240-
241- // Case 2: a placeholder (in our SCC) reaches another placeholder
242- if self . placeholder_reaches_placeholder ( ) {
243- // We know that this SCC contains at least one placeholder
244- // and that at least two placeholders are reachable from
245- // this SCC.
246- //
247- // We try to pick one that isn't in our SCC, if possible.
248- // We *always* pick one that is not equal to the representative.
249-
250- // Unwrap safety: we know both these values are Some, since
251- // there are two reachable placeholders at least.
252- let min_reachable = self . min_reachable_placeholder . unwrap ( ) ;
211+ else {
212+ return None ;
213+ } ;
253214
254- if sccs . scc ( min_reachable ) != sccs . scc ( self . representative ) {
255- return Some ( min_reachable ) ;
256- }
215+ if ! self . min_universe ( ) . cannot_name ( max_reached_universe ) {
216+ return None ;
217+ } ;
257218
258- // Either the largest reachable placeholder is outside our SCC,
259- // or we *must* blame a placeholder in our SCC since the violation
260- // happens inside of it. It's slightly easier to always arbitrarily
261- // pick the largest one, so we do. This also nicely guarantees that
262- // we don't pick the representative, since the representative is the
263- // smallest placeholder by index in the SCC if it is a placeholder
264- // so in order for it to also be the largest reachable min would
265- // have to be equal to max, but then we would only have reached one
266- // placeholder .
267- return Some ( self . max_reachable_placeholder . unwrap ( ) ) ;
268- }
219+ debug ! ( "Universe {max_reached_universe:?} is too large for its SCC!" ) ;
220+ // We originally had a large enough universe to fit all our reachable
221+ // placeholders, but had it lowered because we also reached something
222+ // small-universed. In this case, that's to blame!
223+ let to_blame = if self . representative == large_u_rvid {
224+ debug ! ( "{:?} lowered our universe!" , self . min_reachable_universe ) ;
225+ self . min_reachable_universe . 1
226+ } else {
227+ // The problem is that we, who have a small universe, reach a large one .
228+ large_u_rvid
229+ } ;
269230
270- None
231+ Some ( to_blame )
271232 }
272233}
273234
@@ -1949,14 +1910,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
19491910 // relation, redirect the search to the placeholder to blame.
19501911 if self . is_static ( to) {
19511912 for constraint in path. iter ( ) {
1952- let ConstraintCategory :: IllegalPlaceholder ( culprit_r) = constraint. category else {
1913+ let ConstraintCategory :: IllegalPlaceholder ( culprit_from, culprit_to) =
1914+ constraint. category
1915+ else {
19531916 continue ;
19541917 } ;
19551918
1956- debug ! ( "{culprit_r :?} is the reason {from:?}: 'static!" ) ;
1919+ debug ! ( "{culprit_from:?}: {culprit_to :?} is the reason {from:?}: 'static!" ) ;
19571920 // FIXME: think: this may be for transitive reasons and
19581921 // we may have to do this arbitrarily many times. Or may we?
1959- return self . find_constraint_path_to ( from, |r| r == culprit_r, false ) . unwrap ( ) ;
1922+ return self
1923+ . find_constraint_path_to ( culprit_from, |r| r == culprit_to, false )
1924+ . unwrap ( ) ;
19601925 }
19611926 }
19621927 // No funny business; just return the path!
0 commit comments