11//! Error reporting machinery for lifetime errors.
22
3+ use rustc_data_structures:: frozen:: Frozen ;
34use rustc_data_structures:: fx:: FxIndexSet ;
45use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , MultiSpan } ;
56use rustc_hir as hir;
@@ -10,6 +11,7 @@ use rustc_hir::def::Res::Def;
1011use rustc_hir:: def_id:: DefId ;
1112use rustc_hir:: intravisit:: VisitorExt ;
1213use rustc_hir:: { PolyTraitRef , TyKind , WhereBoundPredicate } ;
14+ use rustc_index:: IndexVec ;
1315use rustc_infer:: infer:: { NllRegionVariableOrigin , RelateParamBound } ;
1416use rustc_middle:: bug;
1517use rustc_middle:: hir:: place:: PlaceBase ;
@@ -23,19 +25,20 @@ use rustc_trait_selection::error_reporting::infer::nice_region_error::{
2325 self , HirTraitObjectVisitor , NiceRegionError , TraitObjectVisitor , find_anon_type,
2426 find_param_with_region, suggest_adding_lifetime_params,
2527} ;
26- use rustc_trait_selection:: error_reporting:: infer:: region:: unexpected_hidden_region_diagnostic;
2728use rustc_trait_selection:: infer:: InferCtxtExt ;
2829use rustc_trait_selection:: traits:: { Obligation , ObligationCtxt } ;
2930use tracing:: { debug, instrument, trace} ;
3031
3132use super :: { OutlivesSuggestionBuilder , RegionName , RegionNameSource } ;
33+ use crate :: constraints:: ConstraintSccIndex ;
3234use crate :: nll:: ConstraintDescription ;
33- use crate :: region_infer:: values:: RegionElement ;
34- use crate :: region_infer:: { BlameConstraint , TypeTest } ;
35+ use crate :: region_infer:: values:: { RegionElement , RegionValues } ;
36+ use crate :: region_infer:: { BlameConstraint , ConstraintSccs , RegionDefinition , TypeTest } ;
3537use crate :: session_diagnostics:: {
3638 FnMutError , FnMutReturnTypeErr , GenericDoesNotLiveLongEnough , LifetimeOutliveErr ,
3739 LifetimeReturnCategoryErr , RequireStaticErr , VarHereDenote ,
3840} ;
41+ use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
3942use crate :: universal_regions:: DefiningTy ;
4043use crate :: { MirBorrowckCtxt , borrowck_errors, fluent_generated as fluent} ;
4144
@@ -108,18 +111,6 @@ pub(crate) enum RegionErrorKind<'tcx> {
108111 /// A generic bound failure for a type test (`T: 'a`).
109112 TypeTestError { type_test : TypeTest < ' tcx > } ,
110113
111- /// An unexpected hidden region for an opaque type.
112- UnexpectedHiddenRegion {
113- /// The span for the member constraint.
114- span : Span ,
115- /// The hidden type.
116- hidden_ty : Ty < ' tcx > ,
117- /// The opaque type.
118- key : ty:: OpaqueTypeKey < ' tcx > ,
119- /// The unexpected region.
120- member_region : ty:: Region < ' tcx > ,
121- } ,
122-
123114 /// Higher-ranked subtyping error.
124115 BoundUniversalRegionError {
125116 /// The placeholder free region.
@@ -156,6 +147,64 @@ pub(crate) struct ErrorConstraintInfo<'tcx> {
156147 pub ( super ) span : Span ,
157148}
158149
150+ /// Like `universal_upper_bound`, but returns an approximation more suitable
151+ /// for diagnostics. If `r` contains multiple disjoint universal regions
152+ /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region.
153+ /// This corresponds to picking named regions over unnamed regions
154+ /// (e.g. picking early-bound regions over a closure late-bound region).
155+ ///
156+ /// This means that the returned value may not be a true upper bound, since
157+ /// only 'static is known to outlive disjoint universal regions.
158+ /// Therefore, this method should only be used in diagnostic code,
159+ /// where displaying *some* named universal region is better than
160+ /// falling back to 'static.
161+ #[ instrument(
162+ level = "debug" ,
163+ skip( universal_region_relations, constraint_sccs, scc_values, definitions)
164+ ) ]
165+ pub ( crate ) fn approx_universal_upper_bound < ' tcx > (
166+ universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
167+ constraint_sccs : & ConstraintSccs ,
168+ scc_values : & RegionValues < ConstraintSccIndex > ,
169+ definitions : & IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
170+ r : RegionVid ,
171+ ) -> RegionVid {
172+ // Find the smallest universal region that contains all other
173+ // universal regions within `region`.
174+ let mut lub = universal_region_relations. universal_regions . fr_fn_body ;
175+ let r_scc = constraint_sccs. scc ( r) ;
176+ let static_r = universal_region_relations. universal_regions . fr_static ;
177+ for ur in scc_values. universal_regions_outlived_by ( r_scc) {
178+ let new_lub = universal_region_relations. postdom_upper_bound ( lub, ur) ;
179+ debug ! ( ?ur, ?lub, ?new_lub) ;
180+ // The upper bound of two non-static regions is static: this
181+ // means we know nothing about the relationship between these
182+ // two regions. Pick a 'better' one to use when constructing
183+ // a diagnostic
184+ if ur != static_r && lub != static_r && new_lub == static_r {
185+ // Prefer the region with an `external_name` - this
186+ // indicates that the region is early-bound, so working with
187+ // it can produce a nicer error.
188+ if definitions[ ur] . external_name . is_some ( ) {
189+ lub = ur;
190+ } else if definitions[ lub] . external_name . is_some ( ) {
191+ // Leave lub unchanged
192+ } else {
193+ // If we get here, we don't have any reason to prefer
194+ // one region over the other. Just pick the
195+ // one with the lower index for now.
196+ lub = std:: cmp:: min ( ur, lub) ;
197+ }
198+ } else {
199+ lub = new_lub;
200+ }
201+ }
202+
203+ debug ! ( ?r, ?lub) ;
204+
205+ lub
206+ }
207+
159208impl < ' infcx , ' tcx > MirBorrowckCtxt < ' _ , ' infcx , ' tcx > {
160209 /// Converts a region inference variable into a `ty::Region` that
161210 /// we can use for error reporting. If `r` is universally bound,
@@ -311,9 +360,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
311360 // buffered in the `MirBorrowckCtxt`.
312361
313362 let mut outlives_suggestion = OutlivesSuggestionBuilder :: default ( ) ;
314- let mut last_unexpected_hidden_region: Option < ( Span , Ty < ' _ > , ty:: OpaqueTypeKey < ' tcx > ) > =
315- None ;
316-
317363 for ( nll_error, _) in nll_errors. into_iter ( ) {
318364 match nll_error {
319365 RegionErrorKind :: TypeTestError { type_test } => {
@@ -363,30 +409,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
363409 }
364410 }
365411
366- RegionErrorKind :: UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
367- let named_ty =
368- self . regioncx . name_regions_for_member_constraint ( self . infcx . tcx , hidden_ty) ;
369- let named_key =
370- self . regioncx . name_regions_for_member_constraint ( self . infcx . tcx , key) ;
371- let named_region = self
372- . regioncx
373- . name_regions_for_member_constraint ( self . infcx . tcx , member_region) ;
374- let diag = unexpected_hidden_region_diagnostic (
375- self . infcx ,
376- self . mir_def_id ( ) ,
377- span,
378- named_ty,
379- named_region,
380- named_key,
381- ) ;
382- if last_unexpected_hidden_region != Some ( ( span, named_ty, named_key) ) {
383- self . buffer_error ( diag) ;
384- last_unexpected_hidden_region = Some ( ( span, named_ty, named_key) ) ;
385- } else {
386- diag. delay_as_bug ( ) ;
387- }
388- }
389-
390412 RegionErrorKind :: BoundUniversalRegionError {
391413 longer_fr,
392414 placeholder,
0 commit comments