@@ -104,8 +104,31 @@ pub(crate) enum RegionErrorKind<'tcx> {
104104 /// A generic bound failure for a type test (`T: 'a`).
105105 TypeTestError { type_test : TypeTest < ' tcx > } ,
106106
107- /// Higher-ranked subtyping error.
108- BoundUniversalRegionError {
107+ /// 'a outlives 'b, and both are placeholders.
108+ PlaceholderOutlivesPlaceholder {
109+ rvid_a : RegionVid ,
110+ rvid_b : RegionVid ,
111+ origin_a : ty:: PlaceholderRegion ,
112+ origin_b : ty:: PlaceholderRegion ,
113+ } ,
114+
115+ /// Indicates that a placeholder has a universe too large for one
116+ /// of its member existentials, or, equivalently, that there is
117+ /// a path through the outlives constraint graph from a placeholder
118+ /// to an existential region that cannot name it.
119+ PlaceholderOutlivesExistentialThatCannotNameIt {
120+ /// the placeholder that transitively outlives an
121+ /// existential that shouldn't leak into it
122+ longer_fr : RegionVid ,
123+ /// The existential leaking into `longer_fr`.
124+ existential_that_cannot_name_longer : RegionVid ,
125+ // `longer_fr`'s originating placeholder region.
126+ placeholder : ty:: PlaceholderRegion ,
127+ } ,
128+
129+ /// Higher-ranked subtyping error. A placeholder outlives
130+ /// either a location or a universal region.
131+ PlaceholderOutlivesLocationOrUniversal {
109132 /// The placeholder free region.
110133 longer_fr : RegionVid ,
111134 /// The region element that erroneously must be outlived by `longer_fr`.
@@ -201,64 +224,38 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
201224 & self ,
202225 diag : & mut Diag < ' _ > ,
203226 lower_bound : RegionVid ,
204- ) {
227+ ) -> Option < ( ) > {
205228 let tcx = self . infcx . tcx ;
206229
207230 // find generic associated types in the given region 'lower_bound'
208- let gat_id_and_generics = self
209- . regioncx
210- . placeholders_contained_in ( lower_bound)
211- . map ( |placeholder| {
212- if let Some ( id) = placeholder. bound . kind . get_id ( )
213- && let Some ( placeholder_id) = id. as_local ( )
214- && let gat_hir_id = tcx. local_def_id_to_hir_id ( placeholder_id)
215- && let Some ( generics_impl) =
216- tcx. parent_hir_node ( tcx. parent_hir_id ( gat_hir_id) ) . generics ( )
217- {
218- Some ( ( gat_hir_id, generics_impl) )
219- } else {
220- None
221- }
222- } )
223- . collect :: < Vec < _ > > ( ) ;
224- debug ! ( ?gat_id_and_generics) ;
231+ let scc = self . regioncx . constraint_sccs ( ) . scc ( lower_bound) ;
232+ let placeholder: ty:: PlaceholderRegion = self . regioncx . placeholder_representative ( scc) ?;
233+ let placeholder_id = placeholder. bound . kind . get_id ( ) ?. as_local ( ) ?;
234+ let gat_hir_id = self . infcx . tcx . local_def_id_to_hir_id ( placeholder_id) ;
235+ let generics_impl =
236+ self . infcx . tcx . parent_hir_node ( self . infcx . tcx . parent_hir_id ( gat_hir_id) ) . generics ( ) ?;
225237
226238 // Look for the where-bound which introduces the placeholder.
227239 // As we're using the HIR, we need to handle both `for<'a> T: Trait<'a>`
228240 // and `T: for<'a> Trait`<'a>.
229241 let mut hrtb_bounds = vec ! [ ] ;
230- gat_id_and_generics. iter ( ) . flatten ( ) . for_each ( |& ( gat_hir_id, generics) | {
231- for pred in generics. predicates {
232- let BoundPredicate ( WhereBoundPredicate { bound_generic_params, bounds, .. } ) =
233- pred. kind
234- else {
235- continue ;
236- } ;
237- if bound_generic_params
238- . iter ( )
239- . rfind ( |bgp| tcx. local_def_id_to_hir_id ( bgp. def_id ) == gat_hir_id)
240- . is_some ( )
241- {
242- for bound in * bounds {
243- hrtb_bounds. push ( bound) ;
244- }
245- } else {
246- for bound in * bounds {
247- if let Trait ( trait_bound) = bound {
248- if trait_bound
249- . bound_generic_params
250- . iter ( )
251- . rfind ( |bgp| tcx. local_def_id_to_hir_id ( bgp. def_id ) == gat_hir_id)
252- . is_some ( )
253- {
254- hrtb_bounds. push ( bound) ;
255- return ;
256- }
257- }
258- }
242+
243+ for pred in generics_impl. predicates {
244+ let BoundPredicate ( WhereBoundPredicate { bound_generic_params, bounds, .. } ) =
245+ pred. kind
246+ else {
247+ continue ;
248+ } ;
249+ if bound_generic_params
250+ . iter ( )
251+ . rfind ( |bgp| self . infcx . tcx . local_def_id_to_hir_id ( bgp. def_id ) == gat_hir_id)
252+ . is_some ( )
253+ {
254+ for bound in * bounds {
255+ hrtb_bounds. push ( bound) ;
259256 }
260257 }
261- } ) ;
258+ }
262259 debug ! ( ?hrtb_bounds) ;
263260
264261 let mut suggestions = vec ! [ ] ;
@@ -304,6 +301,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
304301 Applicability :: MaybeIncorrect ,
305302 ) ;
306303 }
304+ Some ( ( ) )
307305 }
308306
309307 /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
@@ -361,30 +359,56 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
361359 }
362360 }
363361
364- RegionErrorKind :: BoundUniversalRegionError {
362+ RegionErrorKind :: PlaceholderOutlivesLocationOrUniversal {
365363 longer_fr,
366364 placeholder,
367365 error_element,
366+ } => self . report_erroneous_rvid_reaches_placeholder (
367+ longer_fr,
368+ placeholder,
369+ self . regioncx . region_from_element ( longer_fr, & error_element) ,
370+ ) ,
371+ RegionErrorKind :: PlaceholderOutlivesPlaceholder {
372+ rvid_a,
373+ rvid_b,
374+ origin_a,
375+ origin_b,
368376 } => {
369- let error_vid = self . regioncx . region_from_element ( longer_fr, & error_element) ;
377+ debug ! (
378+ "Placeholder mismatch: {rvid_a:?} ({origin_a:?}) reaches {rvid_b:?} ({origin_b:?})"
379+ ) ;
370380
371- // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
372381 let cause = self
373382 . regioncx
374383 . best_blame_constraint (
375- longer_fr ,
376- NllRegionVariableOrigin :: Placeholder ( placeholder ) ,
377- error_vid ,
384+ rvid_a ,
385+ NllRegionVariableOrigin :: Placeholder ( origin_a ) ,
386+ rvid_b ,
378387 )
379388 . 0
380389 . cause ;
381390
382- let universe = placeholder. universe ;
383- let universe_info = self . regioncx . universe_info ( universe) ;
384-
385- universe_info. report_erroneous_element ( self , placeholder, error_element, cause) ;
391+ // FIXME We may be able to shorten the code path here, and immediately
392+ // report a `RegionResolutionError::UpperBoundUniverseConflict`, but
393+ // that's left for a future refactoring.
394+ self . regioncx . universe_info ( origin_a. universe ) . report_erroneous_element (
395+ self ,
396+ origin_a,
397+ Some ( origin_b) ,
398+ cause,
399+ ) ;
386400 }
387401
402+ RegionErrorKind :: PlaceholderOutlivesExistentialThatCannotNameIt {
403+ longer_fr,
404+ existential_that_cannot_name_longer,
405+ placeholder,
406+ } => self . report_erroneous_rvid_reaches_placeholder (
407+ longer_fr,
408+ placeholder,
409+ existential_that_cannot_name_longer,
410+ ) ,
411+
388412 RegionErrorKind :: RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
389413 if is_reported {
390414 self . report_region_error (
0 commit comments