@@ -13,7 +13,7 @@ use rustc::infer::NLLRegionVariableOrigin;
13
13
use rustc:: mir:: { ConstraintCategory , Location , Body } ;
14
14
use rustc:: ty:: { self , RegionVid } ;
15
15
use rustc_data_structures:: indexed_vec:: IndexVec ;
16
- use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
16
+ use rustc_errors:: DiagnosticBuilder ;
17
17
use std:: collections:: VecDeque ;
18
18
use syntax:: errors:: Applicability ;
19
19
use syntax:: symbol:: kw;
@@ -22,7 +22,7 @@ use syntax_pos::Span;
22
22
mod region_name;
23
23
mod var_name;
24
24
25
- crate use self :: region_name:: { RegionName , RegionNameSource } ;
25
+ crate use self :: region_name:: { RegionName , RegionNameSource , RegionErrorNamingCtx } ;
26
26
27
27
impl ConstraintDescription for ConstraintCategory {
28
28
fn description ( & self ) -> & ' static str {
@@ -54,6 +54,30 @@ enum Trace {
54
54
NotVisited ,
55
55
}
56
56
57
+ /// Various pieces of state used when reporting borrow checker errors.
58
+ pub struct ErrorReportingCtx < ' a , ' b , ' tcx > {
59
+ rinfcx : & ' b RegionInferenceContext < ' tcx > ,
60
+ infcx : & ' b InferCtxt < ' a , ' tcx > ,
61
+
62
+ mir_def_id : DefId ,
63
+ body : & ' b Body < ' tcx > ,
64
+ upvars : & ' b [ Upvar ] ,
65
+ }
66
+
67
+ /// Information about the various region constraints involved in a borrow checker error.
68
+ #[ derive( Clone , Debug ) ]
69
+ pub struct ErrorConstraintInfo {
70
+ // fr: outlived_fr
71
+ fr : RegionVid ,
72
+ fr_is_local : bool ,
73
+ outlived_fr : RegionVid ,
74
+ outlived_fr_is_local : bool ,
75
+
76
+ // Category and span for best blame constraint
77
+ category : ConstraintCategory ,
78
+ span : Span ,
79
+ }
80
+
57
81
impl < ' tcx > RegionInferenceContext < ' tcx > {
58
82
/// Tries to find the best constraint to blame for the fact that
59
83
/// `R: from_region`, where `R` is some region that meets
@@ -257,16 +281,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
257
281
/// ```
258
282
///
259
283
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
260
- pub ( super ) fn report_error (
261
- & self ,
284
+ pub ( super ) fn report_error < ' a > (
285
+ & ' a self ,
262
286
body : & Body < ' tcx > ,
263
287
upvars : & [ Upvar ] ,
264
- infcx : & InferCtxt < ' _ , ' tcx > ,
288
+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
265
289
mir_def_id : DefId ,
266
290
fr : RegionVid ,
267
291
outlived_fr : RegionVid ,
268
- errors_buffer : & mut Vec < Diagnostic > ,
269
- ) {
292
+ renctx : & mut RegionErrorNamingCtx ,
293
+ ) -> DiagnosticBuilder < ' a > {
270
294
debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
271
295
272
296
let ( category, _, span) = self . best_blame_constraint ( body, fr, |r| {
@@ -279,8 +303,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
279
303
let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
280
304
let nice = NiceRegionError :: new_from_span ( infcx, span, o, f, Some ( tables) ) ;
281
305
if let Some ( diag) = nice. try_report_from_nll ( ) {
282
- diag. buffer ( errors_buffer) ;
283
- return ;
306
+ return diag;
284
307
}
285
308
}
286
309
@@ -293,45 +316,35 @@ impl<'tcx> RegionInferenceContext<'tcx> {
293
316
"report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
294
317
fr_is_local, outlived_fr_is_local, category
295
318
) ;
319
+
320
+ let errctx = ErrorReportingCtx {
321
+ rinfcx : self ,
322
+ infcx,
323
+ mir_def_id,
324
+ body,
325
+ upvars,
326
+ } ;
327
+
328
+ let errci = ErrorConstraintInfo {
329
+ fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span
330
+ } ;
331
+
296
332
match ( category, fr_is_local, outlived_fr_is_local) {
297
333
( ConstraintCategory :: Return , true , false ) if self . is_closure_fn_mut ( infcx, fr) => {
298
- self . report_fnmut_error (
299
- body,
300
- upvars,
301
- infcx,
302
- mir_def_id,
303
- fr,
304
- outlived_fr,
305
- span,
306
- errors_buffer,
307
- )
334
+ self . report_fnmut_error ( & errctx, & errci, renctx)
308
335
}
309
336
( ConstraintCategory :: Assignment , true , false )
310
- | ( ConstraintCategory :: CallArgument , true , false ) => self . report_escaping_data_error (
311
- body,
312
- upvars,
313
- infcx,
314
- mir_def_id,
315
- fr,
316
- outlived_fr,
317
- category,
318
- span,
319
- errors_buffer,
320
- ) ,
321
- _ => self . report_general_error (
322
- body,
323
- upvars,
324
- infcx,
325
- mir_def_id,
326
- fr,
327
- fr_is_local,
328
- outlived_fr,
329
- outlived_fr_is_local,
330
- category,
331
- span,
332
- errors_buffer,
333
- ) ,
334
- } ;
337
+ | ( ConstraintCategory :: CallArgument , true , false ) => {
338
+ let mut db = self . report_escaping_data_error ( & errctx, & errci, renctx) ;
339
+
340
+ db
341
+ }
342
+ _ => {
343
+ let mut db = self . report_general_error ( & errctx, & errci, renctx) ;
344
+
345
+ db
346
+ }
347
+ }
335
348
}
336
349
337
350
/// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +392,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
379
392
/// ```
380
393
fn report_fnmut_error (
381
394
& self ,
382
- body : & Body < ' tcx > ,
383
- upvars : & [ Upvar ] ,
384
- infcx : & InferCtxt < ' _ , ' tcx > ,
385
- mir_def_id : DefId ,
386
- _fr : RegionVid ,
387
- outlived_fr : RegionVid ,
388
- span : Span ,
389
- errors_buffer : & mut Vec < Diagnostic > ,
390
- ) {
391
- let mut diag = infcx
395
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
396
+ errci : & ErrorConstraintInfo ,
397
+ renctx : & mut RegionErrorNamingCtx ,
398
+ ) -> DiagnosticBuilder < ' _ > {
399
+ let ErrorConstraintInfo {
400
+ outlived_fr, span , ..
401
+ } = errci ;
402
+
403
+ let mut diag = errctx
404
+ . infcx
392
405
. tcx
393
406
. sess
394
- . struct_span_err ( span, "captured variable cannot escape `FnMut` closure body" ) ;
407
+ . struct_span_err ( * span, "captured variable cannot escape `FnMut` closure body" ) ;
395
408
396
409
// We should check if the return type of this closure is in fact a closure - in that
397
410
// case, we can special case the error further.
@@ -403,11 +416,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
403
416
"returns a reference to a captured variable which escapes the closure body"
404
417
} ;
405
418
406
- diag. span_label ( span, message) ;
419
+ diag. span_label ( * span, message) ;
407
420
408
- match self . give_region_a_name ( infcx, body, upvars, mir_def_id, outlived_fr, & mut 1 )
409
- . unwrap ( ) . source
410
- {
421
+ match self . give_region_a_name ( errctx, renctx, * outlived_fr) . unwrap ( ) . source {
411
422
RegionNameSource :: NamedEarlyBoundRegion ( fr_span)
412
423
| RegionNameSource :: NamedFreeRegion ( fr_span)
413
424
| RegionNameSource :: SynthesizedFreeEnvRegion ( fr_span, _)
@@ -427,7 +438,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
427
438
) ;
428
439
diag. note ( "...therefore, they cannot allow references to captured variables to escape" ) ;
429
440
430
- diag. buffer ( errors_buffer ) ;
441
+ diag
431
442
}
432
443
433
444
/// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +455,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
444
455
/// ```
445
456
fn report_escaping_data_error (
446
457
& self ,
447
- body : & Body < ' tcx > ,
448
- upvars : & [ Upvar ] ,
449
- infcx : & InferCtxt < ' _ , ' tcx > ,
450
- mir_def_id : DefId ,
451
- fr : RegionVid ,
452
- outlived_fr : RegionVid ,
453
- category : ConstraintCategory ,
454
- span : Span ,
455
- errors_buffer : & mut Vec < Diagnostic > ,
456
- ) {
458
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
459
+ errci : & ErrorConstraintInfo ,
460
+ renctx : & mut RegionErrorNamingCtx ,
461
+ ) -> DiagnosticBuilder < ' _ > {
462
+ let ErrorReportingCtx {
463
+ infcx, body, upvars, ..
464
+ } = errctx;
465
+
466
+ let ErrorConstraintInfo {
467
+ span, category, ..
468
+ } = errci;
469
+
457
470
let fr_name_and_span =
458
- self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, fr) ;
471
+ self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, errci . fr ) ;
459
472
let outlived_fr_name_and_span =
460
- self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, outlived_fr) ;
473
+ self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, errci . outlived_fr ) ;
461
474
462
475
let escapes_from = match self . universal_regions . defining_ty {
463
476
DefiningTy :: Closure ( ..) => "closure" ,
@@ -469,27 +482,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
469
482
// Revert to the normal error in these cases.
470
483
// Assignments aren't "escapes" in function items.
471
484
if ( fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) )
472
- || ( category == ConstraintCategory :: Assignment && escapes_from == "function" )
485
+ || ( * category == ConstraintCategory :: Assignment && escapes_from == "function" )
473
486
|| escapes_from == "const"
474
487
{
475
488
return self . report_general_error (
476
- body,
477
- upvars,
478
- infcx,
479
- mir_def_id,
480
- fr,
481
- true ,
482
- outlived_fr,
483
- false ,
484
- category,
485
- span,
486
- errors_buffer,
489
+ errctx,
490
+ & ErrorConstraintInfo {
491
+ fr_is_local : true ,
492
+ outlived_fr_is_local : false ,
493
+ .. * errci
494
+ } ,
495
+ renctx,
487
496
) ;
488
497
}
489
498
490
499
let mut diag = borrowck_errors:: borrowed_data_escapes_closure (
491
500
infcx. tcx ,
492
- span,
501
+ * span,
493
502
escapes_from,
494
503
) ;
495
504
@@ -513,12 +522,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
513
522
) ;
514
523
515
524
diag. span_label (
516
- span,
525
+ * span,
517
526
format ! ( "`{}` escapes the {} body here" , fr_name, escapes_from) ,
518
527
) ;
519
528
}
520
529
521
- diag. buffer ( errors_buffer ) ;
530
+ diag
522
531
}
523
532
524
533
/// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +547,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
538
547
/// ```
539
548
fn report_general_error (
540
549
& self ,
541
- body : & Body < ' tcx > ,
542
- upvars : & [ Upvar ] ,
543
- infcx : & InferCtxt < ' _ , ' tcx > ,
544
- mir_def_id : DefId ,
545
- fr : RegionVid ,
546
- fr_is_local : bool ,
547
- outlived_fr : RegionVid ,
548
- outlived_fr_is_local : bool ,
549
- category : ConstraintCategory ,
550
- span : Span ,
551
- errors_buffer : & mut Vec < Diagnostic > ,
552
- ) {
550
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
551
+ errci : & ErrorConstraintInfo ,
552
+ renctx : & mut RegionErrorNamingCtx ,
553
+ ) -> DiagnosticBuilder < ' _ > {
554
+ let ErrorReportingCtx {
555
+ infcx, mir_def_id, ..
556
+ } = errctx;
557
+ let ErrorConstraintInfo {
558
+ fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, ..
559
+ } = errci;
560
+
553
561
let mut diag = infcx. tcx . sess . struct_span_err (
554
- span,
562
+ * span,
555
563
"lifetime may not live long enough"
556
564
) ;
557
565
558
- let counter = & mut 1 ;
559
- let fr_name = self . give_region_a_name (
560
- infcx, body, upvars, mir_def_id, fr, counter) . unwrap ( ) ;
561
- fr_name. highlight_region_name ( & mut diag) ;
562
- let outlived_fr_name =
563
- self . give_region_a_name ( infcx, body, upvars, mir_def_id, outlived_fr, counter) . unwrap ( ) ;
564
- outlived_fr_name. highlight_region_name ( & mut diag) ;
565
-
566
- let mir_def_name = if infcx. tcx . is_closure ( mir_def_id) {
566
+ let mir_def_name = if infcx. tcx . is_closure ( * mir_def_id) {
567
567
"closure"
568
568
} else {
569
569
"function"
570
570
} ;
571
571
572
+ let fr_name = self . give_region_a_name ( errctx, renctx, * fr) . unwrap ( ) ;
573
+ fr_name. highlight_region_name ( & mut diag) ;
574
+ let outlived_fr_name = self . give_region_a_name ( errctx, renctx, * outlived_fr) . unwrap ( ) ;
575
+ outlived_fr_name. highlight_region_name ( & mut diag) ;
576
+
572
577
match ( category, outlived_fr_is_local, fr_is_local) {
573
578
( ConstraintCategory :: Return , true , _) => {
574
579
diag. span_label (
575
- span,
580
+ * span,
576
581
format ! (
577
582
"{} was supposed to return data with lifetime `{}` but it is returning \
578
583
data with lifetime `{}`",
@@ -582,7 +587,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
582
587
}
583
588
_ => {
584
589
diag. span_label (
585
- span,
590
+ * span,
586
591
format ! (
587
592
"{}requires that `{}` must outlive `{}`" ,
588
593
category. description( ) ,
@@ -593,9 +598,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
593
598
}
594
599
}
595
600
596
- self . add_static_impl_trait_suggestion ( infcx, & mut diag, fr, fr_name, outlived_fr) ;
601
+ self . add_static_impl_trait_suggestion ( infcx, & mut diag, * fr, fr_name, * outlived_fr) ;
597
602
598
- diag. buffer ( errors_buffer ) ;
603
+ diag
599
604
}
600
605
601
606
/// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +709,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
704
709
borrow_region,
705
710
|r| self . provides_universal_region ( r, borrow_region, outlived_region)
706
711
) ;
707
- let outlived_fr_name =
708
- self . give_region_a_name ( infcx, body, upvars, mir_def_id, outlived_region, & mut 1 ) ;
712
+
713
+ let mut renctx = RegionErrorNamingCtx :: new ( ) ;
714
+ let errctx = ErrorReportingCtx {
715
+ infcx, body, upvars, mir_def_id,
716
+ rinfcx : self ,
717
+ } ;
718
+ let outlived_fr_name = self . give_region_a_name ( & errctx, & mut renctx, outlived_region) ;
719
+
709
720
( category, from_closure, span, outlived_fr_name)
710
721
}
711
722
0 commit comments