1
1
//! Error reporting machinery for lifetime errors.
2
2
3
- use rustc:: infer:: {
4
- error_reporting:: nice_region_error:: NiceRegionError , InferCtxt , NLLRegionVariableOrigin ,
5
- } ;
3
+ use rustc:: infer:: { error_reporting:: nice_region_error:: NiceRegionError , NLLRegionVariableOrigin } ;
6
4
use rustc:: mir:: ConstraintCategory ;
7
5
use rustc:: ty:: { self , RegionVid , Ty } ;
8
6
use rustc_errors:: { Applicability , DiagnosticBuilder } ;
@@ -14,7 +12,7 @@ use crate::util::borrowck_errors;
14
12
15
13
use crate :: borrow_check:: {
16
14
nll:: ConstraintDescription ,
17
- region_infer:: { values:: RegionElement , RegionInferenceContext , TypeTest } ,
15
+ region_infer:: { values:: RegionElement , TypeTest } ,
18
16
universal_regions:: DefiningTy ,
19
17
MirBorrowckCtxt ,
20
18
} ;
@@ -104,26 +102,28 @@ pub struct ErrorConstraintInfo {
104
102
pub ( super ) span : Span ,
105
103
}
106
104
107
- impl < ' tcx > RegionInferenceContext < ' tcx > {
105
+ impl < ' a , ' tcx > MirBorrowckCtxt < ' a , ' tcx > {
108
106
/// Converts a region inference variable into a `ty::Region` that
109
107
/// we can use for error reporting. If `r` is universally bound,
110
108
/// then we use the name that we have on record for it. If `r` is
111
109
/// existentially bound, then we check its inferred value and try
112
110
/// to find a good name from that. Returns `None` if we can't find
113
111
/// one (e.g., this is just some random part of the CFG).
114
- pub fn to_error_region ( & self , r : RegionVid ) -> Option < ty:: Region < ' tcx > > {
115
- self . to_error_region_vid ( r) . and_then ( |r| self . definitions [ r] . external_name )
112
+ // TODO(mark-i-m): make this private when we move report_region_errors here...
113
+ crate fn to_error_region ( & self , r : RegionVid ) -> Option < ty:: Region < ' tcx > > {
114
+ self . to_error_region_vid ( r)
115
+ . and_then ( |r| self . nonlexical_regioncx . definitions [ r] . external_name )
116
116
}
117
117
118
- /// Returns the [ RegionVid] corresponding to the region returned by
118
+ /// Returns the ` RegionVid` corresponding to the region returned by
119
119
/// `to_error_region`.
120
- pub fn to_error_region_vid ( & self , r : RegionVid ) -> Option < RegionVid > {
121
- if self . universal_regions . is_universal_region ( r) {
120
+ pub ( super ) fn to_error_region_vid ( & self , r : RegionVid ) -> Option < RegionVid > {
121
+ if self . nonlexical_regioncx . universal_regions . is_universal_region ( r) {
122
122
Some ( r)
123
123
} else {
124
- let r_scc = self . constraint_sccs . scc ( r) ;
125
- let upper_bound = self . universal_upper_bound ( r) ;
126
- if self . scc_values . contains ( r_scc, upper_bound) {
124
+ let r_scc = self . nonlexical_regioncx . constraint_sccs . scc ( r) ;
125
+ let upper_bound = self . nonlexical_regioncx . universal_upper_bound ( r) ;
126
+ if self . nonlexical_regioncx . scc_values . contains ( r_scc, upper_bound) {
127
127
self . to_error_region_vid ( upper_bound)
128
128
} else {
129
129
None
@@ -132,11 +132,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
132
132
}
133
133
134
134
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
135
- crate fn is_closure_fn_mut ( & self , infcx : & InferCtxt < ' _ , ' tcx > , fr : RegionVid ) -> bool {
135
+ fn is_closure_fn_mut ( & self , fr : RegionVid ) -> bool {
136
136
if let Some ( ty:: ReFree ( free_region) ) = self . to_error_region ( fr) {
137
137
if let ty:: BoundRegion :: BrEnv = free_region. bound_region {
138
- if let DefiningTy :: Closure ( def_id, substs) = self . universal_regions . defining_ty {
139
- let closure_kind_ty = substs. as_closure ( ) . kind_ty ( def_id, infcx. tcx ) ;
138
+ if let DefiningTy :: Closure ( def_id, substs) =
139
+ self . nonlexical_regioncx . universal_regions . defining_ty
140
+ {
141
+ let closure_kind_ty = substs. as_closure ( ) . kind_ty ( def_id, self . infcx . tcx ) ;
140
142
return Some ( ty:: ClosureKind :: FnMut ) == closure_kind_ty. to_opt_closure_kind ( ) ;
141
143
}
142
144
}
@@ -153,34 +155,35 @@ impl<'tcx> RegionInferenceContext<'tcx> {
153
155
/// ```
154
156
///
155
157
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
156
- pub ( in crate :: borrow_check) fn report_error < ' a > (
157
- & ' a self ,
158
- mbcx : & MirBorrowckCtxt < ' a , ' tcx > ,
158
+ pub ( in crate :: borrow_check) fn report_error (
159
+ & mut self ,
159
160
fr : RegionVid ,
160
161
fr_origin : NLLRegionVariableOrigin ,
161
162
outlived_fr : RegionVid ,
162
163
outlives_suggestion : & mut OutlivesSuggestionBuilder ,
163
164
renctx : & mut RegionErrorNamingCtx ,
164
- ) -> DiagnosticBuilder < ' a > {
165
+ ) {
165
166
debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
166
167
167
- let ( category, _, span) = self . best_blame_constraint ( & mbcx. body , fr, fr_origin, |r| {
168
- self . provides_universal_region ( r, fr, outlived_fr)
169
- } ) ;
168
+ let ( category, _, span) =
169
+ self . nonlexical_regioncx . best_blame_constraint ( & self . body , fr, fr_origin, |r| {
170
+ self . nonlexical_regioncx . provides_universal_region ( r, fr, outlived_fr)
171
+ } ) ;
170
172
171
173
debug ! ( "report_error: category={:?} {:?}" , category, span) ;
172
174
// Check if we can use one of the "nice region errors".
173
175
if let ( Some ( f) , Some ( o) ) = ( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) ) {
174
- let tables = mbcx . infcx . tcx . typeck_tables_of ( mbcx . mir_def_id ) ;
175
- let nice = NiceRegionError :: new_from_span ( mbcx . infcx , span, o, f, Some ( tables) ) ;
176
+ let tables = self . infcx . tcx . typeck_tables_of ( self . mir_def_id ) ;
177
+ let nice = NiceRegionError :: new_from_span ( self . infcx , span, o, f, Some ( tables) ) ;
176
178
if let Some ( diag) = nice. try_report_from_nll ( ) {
177
- return diag;
179
+ diag. buffer ( & mut self . errors_buffer ) ;
180
+ return ;
178
181
}
179
182
}
180
183
181
184
let ( fr_is_local, outlived_fr_is_local) : ( bool , bool ) = (
182
- self . universal_regions . is_local_free_region ( fr) ,
183
- self . universal_regions . is_local_free_region ( outlived_fr) ,
185
+ self . nonlexical_regioncx . universal_regions . is_local_free_region ( fr) ,
186
+ self . nonlexical_regioncx . universal_regions . is_local_free_region ( outlived_fr) ,
184
187
) ;
185
188
186
189
debug ! (
@@ -197,28 +200,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
197
200
span,
198
201
} ;
199
202
200
- match ( category, fr_is_local, outlived_fr_is_local) {
201
- ( ConstraintCategory :: Return , true , false ) if self . is_closure_fn_mut ( mbcx . infcx , fr) => {
202
- self . report_fnmut_error ( mbcx , & errci, renctx)
203
+ let diag = match ( category, fr_is_local, outlived_fr_is_local) {
204
+ ( ConstraintCategory :: Return , true , false ) if self . is_closure_fn_mut ( fr) => {
205
+ self . report_fnmut_error ( & errci, renctx)
203
206
}
204
207
( ConstraintCategory :: Assignment , true , false )
205
208
| ( ConstraintCategory :: CallArgument , true , false ) => {
206
- let mut db = self . report_escaping_data_error ( mbcx , & errci, renctx) ;
209
+ let mut db = self . report_escaping_data_error ( & errci, renctx) ;
207
210
208
- outlives_suggestion. intermediate_suggestion ( mbcx , & errci, renctx, & mut db) ;
211
+ outlives_suggestion. intermediate_suggestion ( self , & errci, renctx, & mut db) ;
209
212
outlives_suggestion. collect_constraint ( fr, outlived_fr) ;
210
213
211
214
db
212
215
}
213
216
_ => {
214
- let mut db = self . report_general_error ( mbcx , & errci, renctx) ;
217
+ let mut db = self . report_general_error ( & errci, renctx) ;
215
218
216
- outlives_suggestion. intermediate_suggestion ( mbcx , & errci, renctx, & mut db) ;
219
+ outlives_suggestion. intermediate_suggestion ( self , & errci, renctx, & mut db) ;
217
220
outlives_suggestion. collect_constraint ( fr, outlived_fr) ;
218
221
219
222
db
220
223
}
221
- }
224
+ } ;
225
+
226
+ diag. buffer ( & mut self . errors_buffer ) ;
222
227
}
223
228
224
229
/// Report a specialized error when `FnMut` closures return a reference to a captured variable.
@@ -239,21 +244,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
239
244
/// ```
240
245
fn report_fnmut_error (
241
246
& self ,
242
- mbcx : & MirBorrowckCtxt < ' _ , ' tcx > ,
243
247
errci : & ErrorConstraintInfo ,
244
248
renctx : & mut RegionErrorNamingCtx ,
245
- ) -> DiagnosticBuilder < ' _ > {
249
+ ) -> DiagnosticBuilder < ' tcx > {
246
250
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
247
251
248
- let mut diag = mbcx
252
+ let mut diag = self
249
253
. infcx
250
254
. tcx
251
255
. sess
252
256
. struct_span_err ( * span, "captured variable cannot escape `FnMut` closure body" ) ;
253
257
254
258
// We should check if the return type of this closure is in fact a closure - in that
255
259
// case, we can special case the error further.
256
- let return_type_is_closure = self . universal_regions . unnormalized_output_ty . is_closure ( ) ;
260
+ let return_type_is_closure =
261
+ self . nonlexical_regioncx . universal_regions . unnormalized_output_ty . is_closure ( ) ;
257
262
let message = if return_type_is_closure {
258
263
"returns a closure that contains a reference to a captured variable, which then \
259
264
escapes the closure body"
@@ -263,7 +268,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
263
268
264
269
diag. span_label ( * span, message) ;
265
270
266
- match self . give_region_a_name ( mbcx , renctx, * outlived_fr) . unwrap ( ) . source {
271
+ match self . give_region_a_name ( renctx, * outlived_fr) . unwrap ( ) . source {
267
272
RegionNameSource :: NamedEarlyBoundRegion ( fr_span)
268
273
| RegionNameSource :: NamedFreeRegion ( fr_span)
269
274
| RegionNameSource :: SynthesizedFreeEnvRegion ( fr_span, _)
@@ -300,28 +305,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
300
305
/// ```
301
306
fn report_escaping_data_error (
302
307
& self ,
303
- mbcx : & MirBorrowckCtxt < ' _ , ' tcx > ,
304
308
errci : & ErrorConstraintInfo ,
305
309
renctx : & mut RegionErrorNamingCtx ,
306
- ) -> DiagnosticBuilder < ' _ > {
310
+ ) -> DiagnosticBuilder < ' tcx > {
307
311
let ErrorConstraintInfo { span, category, .. } = errci;
308
312
309
- let fr_name_and_span = self . get_var_name_and_span_for_region (
310
- mbcx . infcx . tcx ,
311
- & mbcx . body ,
312
- & mbcx . local_names ,
313
- & mbcx . upvars ,
313
+ let fr_name_and_span = self . nonlexical_regioncx . get_var_name_and_span_for_region (
314
+ self . infcx . tcx ,
315
+ & self . body ,
316
+ & self . local_names ,
317
+ & self . upvars ,
314
318
errci. fr ,
315
319
) ;
316
- let outlived_fr_name_and_span = self . get_var_name_and_span_for_region (
317
- mbcx . infcx . tcx ,
318
- & mbcx . body ,
319
- & mbcx . local_names ,
320
- & mbcx . upvars ,
320
+ let outlived_fr_name_and_span = self . nonlexical_regioncx . get_var_name_and_span_for_region (
321
+ self . infcx . tcx ,
322
+ & self . body ,
323
+ & self . local_names ,
324
+ & self . upvars ,
321
325
errci. outlived_fr ,
322
326
) ;
323
327
324
- let escapes_from = match self . universal_regions . defining_ty {
328
+ let escapes_from = match self . nonlexical_regioncx . universal_regions . defining_ty {
325
329
DefiningTy :: Closure ( ..) => "closure" ,
326
330
DefiningTy :: Generator ( ..) => "generator" ,
327
331
DefiningTy :: FnDef ( ..) => "function" ,
@@ -335,14 +339,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
335
339
|| escapes_from == "const"
336
340
{
337
341
return self . report_general_error (
338
- mbcx,
339
342
& ErrorConstraintInfo { fr_is_local : true , outlived_fr_is_local : false , ..* errci } ,
340
343
renctx,
341
344
) ;
342
345
}
343
346
344
347
let mut diag =
345
- borrowck_errors:: borrowed_data_escapes_closure ( mbcx . infcx . tcx , * span, escapes_from) ;
348
+ borrowck_errors:: borrowed_data_escapes_closure ( self . infcx . tcx , * span, escapes_from) ;
346
349
347
350
if let Some ( ( Some ( outlived_fr_name) , outlived_fr_span) ) = outlived_fr_name_and_span {
348
351
diag. span_label (
@@ -386,10 +389,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
386
389
/// ```
387
390
fn report_general_error (
388
391
& self ,
389
- mbcx : & MirBorrowckCtxt < ' _ , ' tcx > ,
390
392
errci : & ErrorConstraintInfo ,
391
393
renctx : & mut RegionErrorNamingCtx ,
392
- ) -> DiagnosticBuilder < ' _ > {
394
+ ) -> DiagnosticBuilder < ' tcx > {
393
395
let ErrorConstraintInfo {
394
396
fr,
395
397
fr_is_local,
@@ -401,14 +403,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
401
403
} = errci;
402
404
403
405
let mut diag =
404
- mbcx . infcx . tcx . sess . struct_span_err ( * span, "lifetime may not live long enough" ) ;
406
+ self . infcx . tcx . sess . struct_span_err ( * span, "lifetime may not live long enough" ) ;
405
407
406
408
let mir_def_name =
407
- if mbcx . infcx . tcx . is_closure ( mbcx . mir_def_id ) { "closure" } else { "function" } ;
409
+ if self . infcx . tcx . is_closure ( self . mir_def_id ) { "closure" } else { "function" } ;
408
410
409
- let fr_name = self . give_region_a_name ( mbcx , renctx, * fr) . unwrap ( ) ;
411
+ let fr_name = self . give_region_a_name ( renctx, * fr) . unwrap ( ) ;
410
412
fr_name. highlight_region_name ( & mut diag) ;
411
- let outlived_fr_name = self . give_region_a_name ( mbcx , renctx, * outlived_fr) . unwrap ( ) ;
413
+ let outlived_fr_name = self . give_region_a_name ( renctx, * outlived_fr) . unwrap ( ) ;
412
414
outlived_fr_name. highlight_region_name ( & mut diag) ;
413
415
414
416
match ( category, outlived_fr_is_local, fr_is_local) {
@@ -435,7 +437,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
435
437
}
436
438
}
437
439
438
- self . add_static_impl_trait_suggestion ( mbcx . infcx , & mut diag, * fr, fr_name, * outlived_fr) ;
440
+ self . add_static_impl_trait_suggestion ( & mut diag, * fr, fr_name, * outlived_fr) ;
439
441
440
442
diag
441
443
}
@@ -451,8 +453,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
451
453
/// ```
452
454
fn add_static_impl_trait_suggestion (
453
455
& self ,
454
- infcx : & InferCtxt < ' _ , ' tcx > ,
455
- diag : & mut DiagnosticBuilder < ' _ > ,
456
+ diag : & mut DiagnosticBuilder < ' tcx > ,
456
457
fr : RegionVid ,
457
458
// We need to pass `fr_name` - computing it again will label it twice.
458
459
fr_name : RegionName ,
@@ -461,20 +462,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
461
462
if let ( Some ( f) , Some ( ty:: RegionKind :: ReStatic ) ) =
462
463
( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) )
463
464
{
464
- if let Some ( ( ty:: TyS { kind : ty:: Opaque ( did, substs) , .. } , _) ) = infcx
465
+ if let Some ( ( ty:: TyS { kind : ty:: Opaque ( did, substs) , .. } , _) ) = self
466
+ . infcx
465
467
. tcx
466
468
. is_suitable_region ( f)
467
469
. map ( |r| r. def_id )
468
- . map ( |id| infcx. tcx . return_type_impl_trait ( id) )
470
+ . map ( |id| self . infcx . tcx . return_type_impl_trait ( id) )
469
471
. unwrap_or ( None )
470
472
{
471
473
// Check whether or not the impl trait return type is intended to capture
472
474
// data with the static lifetime.
473
475
//
474
476
// eg. check for `impl Trait + 'static` instead of `impl Trait`.
475
477
let has_static_predicate = {
476
- let predicates_of = infcx. tcx . predicates_of ( * did) ;
477
- let bounds = predicates_of. instantiate ( infcx. tcx , substs) ;
478
+ let predicates_of = self . infcx . tcx . predicates_of ( * did) ;
479
+ let bounds = predicates_of. instantiate ( self . infcx . tcx , substs) ;
478
480
479
481
let mut found = false ;
480
482
for predicate in bounds. predicates {
@@ -502,8 +504,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
502
504
diag. help ( & format ! ( "consider replacing `{}` with `{}`" , fr_name, static_str) ) ;
503
505
} else {
504
506
// Otherwise, we should suggest adding a constraint on the return type.
505
- let span = infcx. tcx . def_span ( * did) ;
506
- if let Ok ( snippet) = infcx. tcx . sess . source_map ( ) . span_to_snippet ( span) {
507
+ let span = self . infcx . tcx . def_span ( * did) ;
508
+ if let Ok ( snippet) = self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( span) {
507
509
let suggestable_fr_name = if fr_name. was_named ( ) {
508
510
fr_name. to_string ( )
509
511
} else {
0 commit comments