@@ -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,39 @@ 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
+ /// The region inference context used for borrow chekcing this MIR body.
60
+ #[ allow( dead_code) ] // FIXME(mark-i-m): used by outlives suggestions
61
+ region_infcx : & ' b RegionInferenceContext < ' tcx > ,
62
+
63
+ /// The inference context used for type checking.
64
+ infcx : & ' b InferCtxt < ' a , ' tcx > ,
65
+
66
+ /// The MIR def we are reporting errors on.
67
+ mir_def_id : DefId ,
68
+
69
+ /// The MIR body we are reporting errors on (for convenience).
70
+ body : & ' b Body < ' tcx > ,
71
+
72
+ /// Any upvars for the MIR body we have kept track of during borrow checking.
73
+ upvars : & ' b [ Upvar ] ,
74
+ }
75
+
76
+ /// Information about the various region constraints involved in a borrow checker error.
77
+ #[ derive( Clone , Debug ) ]
78
+ pub struct ErrorConstraintInfo {
79
+ // fr: outlived_fr
80
+ fr : RegionVid ,
81
+ fr_is_local : bool ,
82
+ outlived_fr : RegionVid ,
83
+ outlived_fr_is_local : bool ,
84
+
85
+ // Category and span for best blame constraint
86
+ category : ConstraintCategory ,
87
+ span : Span ,
88
+ }
89
+
57
90
impl < ' tcx > RegionInferenceContext < ' tcx > {
58
91
/// Tries to find the best constraint to blame for the fact that
59
92
/// `R: from_region`, where `R` is some region that meets
@@ -257,16 +290,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
257
290
/// ```
258
291
///
259
292
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
260
- pub ( super ) fn report_error (
261
- & self ,
293
+ pub ( super ) fn report_error < ' a > (
294
+ & ' a self ,
262
295
body : & Body < ' tcx > ,
263
296
upvars : & [ Upvar ] ,
264
- infcx : & InferCtxt < ' _ , ' tcx > ,
297
+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
265
298
mir_def_id : DefId ,
266
299
fr : RegionVid ,
267
300
outlived_fr : RegionVid ,
268
- errors_buffer : & mut Vec < Diagnostic > ,
269
- ) {
301
+ renctx : & mut RegionErrorNamingCtx ,
302
+ ) -> DiagnosticBuilder < ' a > {
270
303
debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
271
304
272
305
let ( category, _, span) = self . best_blame_constraint ( body, fr, |r| {
@@ -279,8 +312,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
279
312
let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
280
313
let nice = NiceRegionError :: new_from_span ( infcx, span, o, f, Some ( tables) ) ;
281
314
if let Some ( diag) = nice. try_report_from_nll ( ) {
282
- diag. buffer ( errors_buffer) ;
283
- return ;
315
+ return diag;
284
316
}
285
317
}
286
318
@@ -293,45 +325,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
293
325
"report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
294
326
fr_is_local, outlived_fr_is_local, category
295
327
) ;
328
+
329
+ let errctx = ErrorReportingCtx {
330
+ region_infcx : self ,
331
+ infcx,
332
+ mir_def_id,
333
+ body,
334
+ upvars,
335
+ } ;
336
+
337
+ let errci = ErrorConstraintInfo {
338
+ fr, outlived_fr, fr_is_local, outlived_fr_is_local, category, span
339
+ } ;
340
+
296
341
match ( category, fr_is_local, outlived_fr_is_local) {
297
342
( 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
- )
343
+ self . report_fnmut_error ( & errctx, & errci, renctx)
308
344
}
309
345
( 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
- } ;
346
+ | ( ConstraintCategory :: CallArgument , true , false ) =>
347
+ self . report_escaping_data_error ( & errctx, & errci, renctx) ,
348
+ _ => self . report_general_error ( & errctx, & errci, renctx) ,
349
+ }
335
350
}
336
351
337
352
/// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +394,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
379
394
/// ```
380
395
fn report_fnmut_error (
381
396
& 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
397
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
398
+ errci : & ErrorConstraintInfo ,
399
+ renctx : & mut RegionErrorNamingCtx ,
400
+ ) -> DiagnosticBuilder < ' _ > {
401
+ let ErrorConstraintInfo {
402
+ outlived_fr, span , ..
403
+ } = errci ;
404
+
405
+ let mut diag = errctx
406
+ . infcx
392
407
. tcx
393
408
. sess
394
- . struct_span_err ( span, "captured variable cannot escape `FnMut` closure body" ) ;
409
+ . struct_span_err ( * span, "captured variable cannot escape `FnMut` closure body" ) ;
395
410
396
411
// We should check if the return type of this closure is in fact a closure - in that
397
412
// case, we can special case the error further.
@@ -403,11 +418,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
403
418
"returns a reference to a captured variable which escapes the closure body"
404
419
} ;
405
420
406
- diag. span_label ( span, message) ;
421
+ diag. span_label ( * span, message) ;
407
422
408
- match self . give_region_a_name ( infcx, body, upvars, mir_def_id, outlived_fr, & mut 1 )
409
- . unwrap ( ) . source
410
- {
423
+ match self . give_region_a_name ( errctx, renctx, * outlived_fr) . unwrap ( ) . source {
411
424
RegionNameSource :: NamedEarlyBoundRegion ( fr_span)
412
425
| RegionNameSource :: NamedFreeRegion ( fr_span)
413
426
| RegionNameSource :: SynthesizedFreeEnvRegion ( fr_span, _)
@@ -427,7 +440,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
427
440
) ;
428
441
diag. note ( "...therefore, they cannot allow references to captured variables to escape" ) ;
429
442
430
- diag. buffer ( errors_buffer ) ;
443
+ diag
431
444
}
432
445
433
446
/// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +457,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
444
457
/// ```
445
458
fn report_escaping_data_error (
446
459
& 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
- ) {
460
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
461
+ errci : & ErrorConstraintInfo ,
462
+ renctx : & mut RegionErrorNamingCtx ,
463
+ ) -> DiagnosticBuilder < ' _ > {
464
+ let ErrorReportingCtx {
465
+ infcx, body, upvars, ..
466
+ } = errctx;
467
+
468
+ let ErrorConstraintInfo {
469
+ span, category, ..
470
+ } = errci;
471
+
457
472
let fr_name_and_span =
458
- self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, fr) ;
473
+ self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, errci . fr ) ;
459
474
let outlived_fr_name_and_span =
460
- self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, outlived_fr) ;
475
+ self . get_var_name_and_span_for_region ( infcx. tcx , body, upvars, errci . outlived_fr ) ;
461
476
462
477
let escapes_from = match self . universal_regions . defining_ty {
463
478
DefiningTy :: Closure ( ..) => "closure" ,
@@ -469,27 +484,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
469
484
// Revert to the normal error in these cases.
470
485
// Assignments aren't "escapes" in function items.
471
486
if ( fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) )
472
- || ( category == ConstraintCategory :: Assignment && escapes_from == "function" )
487
+ || ( * category == ConstraintCategory :: Assignment && escapes_from == "function" )
473
488
|| escapes_from == "const"
474
489
{
475
490
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,
491
+ errctx,
492
+ & ErrorConstraintInfo {
493
+ fr_is_local : true ,
494
+ outlived_fr_is_local : false ,
495
+ .. * errci
496
+ } ,
497
+ renctx,
487
498
) ;
488
499
}
489
500
490
501
let mut diag = borrowck_errors:: borrowed_data_escapes_closure (
491
502
infcx. tcx ,
492
- span,
503
+ * span,
493
504
escapes_from,
494
505
) ;
495
506
@@ -513,12 +524,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
513
524
) ;
514
525
515
526
diag. span_label (
516
- span,
527
+ * span,
517
528
format ! ( "`{}` escapes the {} body here" , fr_name, escapes_from) ,
518
529
) ;
519
530
}
520
531
521
- diag. buffer ( errors_buffer ) ;
532
+ diag
522
533
}
523
534
524
535
/// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +549,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
538
549
/// ```
539
550
fn report_general_error (
540
551
& 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
- ) {
552
+ errctx : & ErrorReportingCtx < ' _ , ' _ , ' tcx > ,
553
+ errci : & ErrorConstraintInfo ,
554
+ renctx : & mut RegionErrorNamingCtx ,
555
+ ) -> DiagnosticBuilder < ' _ > {
556
+ let ErrorReportingCtx {
557
+ infcx, mir_def_id, ..
558
+ } = errctx;
559
+ let ErrorConstraintInfo {
560
+ fr, fr_is_local, outlived_fr, outlived_fr_is_local, span, category, ..
561
+ } = errci;
562
+
553
563
let mut diag = infcx. tcx . sess . struct_span_err (
554
- span,
564
+ * span,
555
565
"lifetime may not live long enough"
556
566
) ;
557
567
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) {
568
+ let mir_def_name = if infcx. tcx . is_closure ( * mir_def_id) {
567
569
"closure"
568
570
} else {
569
571
"function"
570
572
} ;
571
573
574
+ let fr_name = self . give_region_a_name ( errctx, renctx, * fr) . unwrap ( ) ;
575
+ fr_name. highlight_region_name ( & mut diag) ;
576
+ let outlived_fr_name = self . give_region_a_name ( errctx, renctx, * outlived_fr) . unwrap ( ) ;
577
+ outlived_fr_name. highlight_region_name ( & mut diag) ;
578
+
572
579
match ( category, outlived_fr_is_local, fr_is_local) {
573
580
( ConstraintCategory :: Return , true , _) => {
574
581
diag. span_label (
575
- span,
582
+ * span,
576
583
format ! (
577
584
"{} was supposed to return data with lifetime `{}` but it is returning \
578
585
data with lifetime `{}`",
@@ -582,7 +589,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
582
589
}
583
590
_ => {
584
591
diag. span_label (
585
- span,
592
+ * span,
586
593
format ! (
587
594
"{}requires that `{}` must outlive `{}`" ,
588
595
category. description( ) ,
@@ -593,9 +600,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
593
600
}
594
601
}
595
602
596
- self . add_static_impl_trait_suggestion ( infcx, & mut diag, fr, fr_name, outlived_fr) ;
603
+ self . add_static_impl_trait_suggestion ( infcx, & mut diag, * fr, fr_name, * outlived_fr) ;
597
604
598
- diag. buffer ( errors_buffer ) ;
605
+ diag
599
606
}
600
607
601
608
/// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +711,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
704
711
borrow_region,
705
712
|r| self . provides_universal_region ( r, borrow_region, outlived_region)
706
713
) ;
707
- let outlived_fr_name =
708
- self . give_region_a_name ( infcx, body, upvars, mir_def_id, outlived_region, & mut 1 ) ;
714
+
715
+ let mut renctx = RegionErrorNamingCtx :: new ( ) ;
716
+ let errctx = ErrorReportingCtx {
717
+ infcx, body, upvars, mir_def_id,
718
+ region_infcx : self ,
719
+ } ;
720
+ let outlived_fr_name = self . give_region_a_name ( & errctx, & mut renctx, outlived_region) ;
721
+
709
722
( category, from_closure, span, outlived_fr_name)
710
723
}
711
724
0 commit comments