1
1
//! Error reporting machinery for lifetime errors.
2
2
3
+ use rustc_data_structures:: frozen:: Frozen ;
3
4
use rustc_data_structures:: fx:: FxIndexSet ;
4
5
use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , MultiSpan } ;
5
6
use rustc_hir as hir;
@@ -10,6 +11,7 @@ use rustc_hir::def::Res::Def;
10
11
use rustc_hir:: def_id:: DefId ;
11
12
use rustc_hir:: intravisit:: VisitorExt ;
12
13
use rustc_hir:: { PolyTraitRef , TyKind , WhereBoundPredicate } ;
14
+ use rustc_index:: IndexVec ;
13
15
use rustc_infer:: infer:: { NllRegionVariableOrigin , RelateParamBound } ;
14
16
use rustc_middle:: bug;
15
17
use rustc_middle:: hir:: place:: PlaceBase ;
@@ -23,19 +25,20 @@ use rustc_trait_selection::error_reporting::infer::nice_region_error::{
23
25
self , HirTraitObjectVisitor , NiceRegionError , TraitObjectVisitor , find_anon_type,
24
26
find_param_with_region, suggest_adding_lifetime_params,
25
27
} ;
26
- use rustc_trait_selection:: error_reporting:: infer:: region:: unexpected_hidden_region_diagnostic;
27
28
use rustc_trait_selection:: infer:: InferCtxtExt ;
28
29
use rustc_trait_selection:: traits:: { Obligation , ObligationCtxt } ;
29
30
use tracing:: { debug, instrument, trace} ;
30
31
31
32
use super :: { OutlivesSuggestionBuilder , RegionName , RegionNameSource } ;
33
+ use crate :: constraints:: ConstraintSccIndex ;
32
34
use 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 } ;
35
37
use crate :: session_diagnostics:: {
36
38
FnMutError , FnMutReturnTypeErr , GenericDoesNotLiveLongEnough , LifetimeOutliveErr ,
37
39
LifetimeReturnCategoryErr , RequireStaticErr , VarHereDenote ,
38
40
} ;
41
+ use crate :: type_check:: free_region_relations:: UniversalRegionRelations ;
39
42
use crate :: universal_regions:: DefiningTy ;
40
43
use crate :: { MirBorrowckCtxt , borrowck_errors, fluent_generated as fluent} ;
41
44
@@ -108,18 +111,6 @@ pub(crate) enum RegionErrorKind<'tcx> {
108
111
/// A generic bound failure for a type test (`T: 'a`).
109
112
TypeTestError { type_test : TypeTest < ' tcx > } ,
110
113
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
-
123
114
/// Higher-ranked subtyping error.
124
115
BoundUniversalRegionError {
125
116
/// The placeholder free region.
@@ -156,6 +147,64 @@ pub(crate) struct ErrorConstraintInfo<'tcx> {
156
147
pub ( super ) span : Span ,
157
148
}
158
149
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
+
159
208
impl < ' infcx , ' tcx > MirBorrowckCtxt < ' _ , ' infcx , ' tcx > {
160
209
/// Converts a region inference variable into a `ty::Region` that
161
210
/// we can use for error reporting. If `r` is universally bound,
@@ -311,9 +360,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
311
360
// buffered in the `MirBorrowckCtxt`.
312
361
313
362
let mut outlives_suggestion = OutlivesSuggestionBuilder :: default ( ) ;
314
- let mut last_unexpected_hidden_region: Option < ( Span , Ty < ' _ > , ty:: OpaqueTypeKey < ' tcx > ) > =
315
- None ;
316
-
317
363
for ( nll_error, _) in nll_errors. into_iter ( ) {
318
364
match nll_error {
319
365
RegionErrorKind :: TypeTestError { type_test } => {
@@ -363,30 +409,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
363
409
}
364
410
}
365
411
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
-
390
412
RegionErrorKind :: BoundUniversalRegionError {
391
413
longer_fr,
392
414
placeholder,
0 commit comments