@@ -112,6 +112,9 @@ struct RegionTracker {
112
112
113
113
// Metadata about reachable placeholders
114
114
reachable_placeholders : PlaceholderReachability ,
115
+
116
+ // Track the existential with the smallest universe we reach.
117
+ min_universe_reachable_existential : Option < ( UniverseIndex , RegionVid ) > ,
115
118
}
116
119
117
120
impl scc:: Annotation for RegionTracker {
@@ -122,14 +125,25 @@ impl scc::Annotation for RegionTracker {
122
125
} else {
123
126
self . min_universe
124
127
} ;
128
+
129
+ let min_universe_reachable_existential = smallest_reachable_existential (
130
+ self . min_universe_reachable_existential ,
131
+ other. min_universe_reachable_existential ,
132
+ ) ;
125
133
Self {
126
134
reachable_placeholders : self . reachable_placeholders . merge ( other. reachable_placeholders ) ,
127
135
min_universe,
128
136
representative : self . representative . merge_scc ( other. representative ) ,
137
+ min_universe_reachable_existential,
129
138
}
130
139
}
131
140
132
141
fn merge_reached ( mut self , other : Self ) -> Self {
142
+ self . min_universe_reachable_existential = smallest_reachable_existential (
143
+ self . min_universe_reachable_existential ,
144
+ other. min_universe_reachable_existential ,
145
+ ) ;
146
+
133
147
// This detail is subtle. We stop early here, because there may be multiple
134
148
// illegally reached universes, but they are not equally good as blame candidates.
135
149
// In general, the ones with the smallest indices of their RegionVids will
@@ -150,14 +164,25 @@ impl scc::Annotation for RegionTracker {
150
164
}
151
165
}
152
166
167
+ fn smallest_reachable_existential (
168
+ min_universe_reachable_existential_1 : Option < ( UniverseIndex , RegionVid ) > ,
169
+ min_universe_reachable_existential_2 : Option < ( UniverseIndex , RegionVid ) > ,
170
+ ) -> Option < ( UniverseIndex , RegionVid ) > {
171
+ match ( min_universe_reachable_existential_1, min_universe_reachable_existential_2) {
172
+ ( Some ( a) , Some ( b) ) => Some ( std:: cmp:: min ( a, b) ) ,
173
+ ( a, b) => a. or ( b) ,
174
+ }
175
+ }
176
+
153
177
impl RegionTracker {
154
178
fn new ( representative : RegionVid , definition : & RegionDefinition < ' _ > ) -> Self {
155
179
let universe_and_rvid = ( definition. universe , representative) ;
156
- let ( representative, reachable_placeholders) = {
180
+ let ( representative, reachable_placeholders, min_universe_reachable_existential ) = {
157
181
match definition. origin {
158
182
NllRegionVariableOrigin :: FreeRegion => (
159
183
Representative :: FreeRegion ( representative) ,
160
184
PlaceholderReachability :: NoPlaceholders ,
185
+ None ,
161
186
) ,
162
187
NllRegionVariableOrigin :: Placeholder ( _) => (
163
188
Representative :: Placeholder ( representative) ,
@@ -166,14 +191,21 @@ impl RegionTracker {
166
191
min_placeholder : representative,
167
192
max_placeholder : representative,
168
193
} ,
194
+ None ,
169
195
) ,
170
196
NllRegionVariableOrigin :: Existential { .. } => (
171
197
Representative :: Existential ( representative) ,
172
198
PlaceholderReachability :: NoPlaceholders ,
199
+ Some ( ( definition. universe , representative) ) ,
173
200
) ,
174
201
}
175
202
} ;
176
- Self { representative, min_universe : universe_and_rvid, reachable_placeholders }
203
+ Self {
204
+ representative,
205
+ min_universe : universe_and_rvid,
206
+ reachable_placeholders,
207
+ min_universe_reachable_existential,
208
+ }
177
209
}
178
210
179
211
/// The smallest-indexed universe reachable from and/or in this SCC.
@@ -237,6 +269,16 @@ impl RegionTracker {
237
269
238
270
Some ( ( max_u_rvid, max_u) )
239
271
}
272
+
273
+ /// Check for the second and final type of placeholder leak,
274
+ /// where an existential `'e` outlives (transitively) a placeholder `p`
275
+ /// and `e` cannot name `p`.
276
+ ///
277
+ /// Returns *a* culprit (though there may be more than one).
278
+ fn reaches_existential_that_cannot_name_us ( & self ) -> Option < RegionVid > {
279
+ let ( min_u, min_rvid) = self . min_universe_reachable_existential ?;
280
+ ( min_u < self . min_universe ( ) ) . then_some ( min_rvid)
281
+ }
240
282
}
241
283
242
284
impl scc:: Annotations < RegionVid , ConstraintSccIndex , RegionTracker >
@@ -279,10 +321,19 @@ fn find_placeholder_mismatch_errors<'tcx>(
279
321
} ;
280
322
281
323
let scc = sccs. scc ( rvid) ;
324
+ let annotation = annotations. scc_to_annotation [ scc] ;
282
325
283
- let Some ( other_placeholder) =
284
- annotations. scc_to_annotation [ scc] . reaches_other_placeholder ( rvid)
285
- else {
326
+ if let Some ( existental_that_cannot_name_rvid) =
327
+ annotation. reaches_existential_that_cannot_name_us ( )
328
+ {
329
+ errors_buffer. push ( RegionErrorKind :: PlaceholderReachesExistentialThatCannotNameIt {
330
+ longer_fr : rvid,
331
+ existental_that_cannot_name_longer : existental_that_cannot_name_rvid,
332
+ placeholder : origin_a,
333
+ } )
334
+ }
335
+
336
+ let Some ( other_placeholder) = annotation. reaches_other_placeholder ( rvid) else {
286
337
trace ! ( "{rvid:?} reaches no other placeholders" ) ;
287
338
continue ;
288
339
} ;
@@ -486,6 +537,7 @@ fn rewrite_outlives<'tcx>(
486
537
for scc in sccs. all_sccs ( ) {
487
538
let annotation: RegionTracker = annotations. scc_to_annotation [ scc] ;
488
539
if scc == sccs. scc ( fr_static) {
540
+ trace ! ( "Skipping adding 'static: 'static." ) ;
489
541
// No use adding 'static: 'static.
490
542
continue ;
491
543
}
@@ -501,7 +553,10 @@ fn rewrite_outlives<'tcx>(
501
553
502
554
let min_u = annotation. min_universe ( ) ;
503
555
504
- debug ! ( "Universe {max_u:?} is too large for its SCC!" ) ;
556
+ debug ! (
557
+ "Universe {max_u:?} is too large for its SCC, represented by {:?}" ,
558
+ annotation. representative
559
+ ) ;
505
560
let blame_to = if annotation. representative . rvid ( ) == max_u_rvid {
506
561
// We originally had a large enough universe to fit all our reachable
507
562
// placeholders, but had it lowered because we also absorbed something
0 commit comments