@@ -13,7 +13,7 @@ use rustc::infer::NLLRegionVariableOrigin;
1313use rustc:: mir:: { ConstraintCategory , Location , Body } ;
1414use rustc:: ty:: { self , RegionVid } ;
1515use rustc_data_structures:: indexed_vec:: IndexVec ;
16- use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
16+ use rustc_errors:: DiagnosticBuilder ;
1717use std:: collections:: VecDeque ;
1818use syntax:: errors:: Applicability ;
1919use syntax:: symbol:: kw;
@@ -22,7 +22,7 @@ use syntax_pos::Span;
2222mod region_name;
2323mod var_name;
2424
25- crate use self :: region_name:: { RegionName , RegionNameSource } ;
25+ crate use self :: region_name:: { RegionName , RegionNameSource , RegionErrorNamingCtx } ;
2626
2727impl ConstraintDescription for ConstraintCategory {
2828 fn description ( & self ) -> & ' static str {
@@ -54,6 +54,39 @@ enum Trace {
5454 NotVisited ,
5555}
5656
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+
5790impl < ' tcx > RegionInferenceContext < ' tcx > {
5891 /// Tries to find the best constraint to blame for the fact that
5992 /// `R: from_region`, where `R` is some region that meets
@@ -257,16 +290,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
257290 /// ```
258291 ///
259292 /// 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 ,
262295 body : & Body < ' tcx > ,
263296 upvars : & [ Upvar ] ,
264- infcx : & InferCtxt < ' _ , ' tcx > ,
297+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
265298 mir_def_id : DefId ,
266299 fr : RegionVid ,
267300 outlived_fr : RegionVid ,
268- errors_buffer : & mut Vec < Diagnostic > ,
269- ) {
301+ renctx : & mut RegionErrorNamingCtx ,
302+ ) -> DiagnosticBuilder < ' a > {
270303 debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
271304
272305 let ( category, _, span) = self . best_blame_constraint ( body, fr, |r| {
@@ -279,8 +312,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
279312 let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
280313 let nice = NiceRegionError :: new_from_span ( infcx, span, o, f, Some ( tables) ) ;
281314 if let Some ( diag) = nice. try_report_from_nll ( ) {
282- diag. buffer ( errors_buffer) ;
283- return ;
315+ return diag;
284316 }
285317 }
286318
@@ -293,45 +325,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
293325 "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
294326 fr_is_local, outlived_fr_is_local, category
295327 ) ;
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+
296341 match ( category, fr_is_local, outlived_fr_is_local) {
297342 ( 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)
308344 }
309345 ( 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+ }
335350 }
336351
337352 /// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +394,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
379394 /// ```
380395 fn report_fnmut_error (
381396 & 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
392407 . tcx
393408 . 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" ) ;
395410
396411 // We should check if the return type of this closure is in fact a closure - in that
397412 // case, we can special case the error further.
@@ -403,11 +418,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
403418 "returns a reference to a captured variable which escapes the closure body"
404419 } ;
405420
406- diag. span_label ( span, message) ;
421+ diag. span_label ( * span, message) ;
407422
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 {
411424 RegionNameSource :: NamedEarlyBoundRegion ( fr_span)
412425 | RegionNameSource :: NamedFreeRegion ( fr_span)
413426 | RegionNameSource :: SynthesizedFreeEnvRegion ( fr_span, _)
@@ -427,7 +440,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
427440 ) ;
428441 diag. note ( "...therefore, they cannot allow references to captured variables to escape" ) ;
429442
430- diag. buffer ( errors_buffer ) ;
443+ diag
431444 }
432445
433446 /// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +457,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
444457 /// ```
445458 fn report_escaping_data_error (
446459 & 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+
457472 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 ) ;
459474 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 ) ;
461476
462477 let escapes_from = match self . universal_regions . defining_ty {
463478 DefiningTy :: Closure ( ..) => "closure" ,
@@ -469,27 +484,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
469484 // Revert to the normal error in these cases.
470485 // Assignments aren't "escapes" in function items.
471486 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" )
473488 || escapes_from == "const"
474489 {
475490 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,
487498 ) ;
488499 }
489500
490501 let mut diag = borrowck_errors:: borrowed_data_escapes_closure (
491502 infcx. tcx ,
492- span,
503+ * span,
493504 escapes_from,
494505 ) ;
495506
@@ -513,12 +524,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
513524 ) ;
514525
515526 diag. span_label (
516- span,
527+ * span,
517528 format ! ( "`{}` escapes the {} body here" , fr_name, escapes_from) ,
518529 ) ;
519530 }
520531
521- diag. buffer ( errors_buffer ) ;
532+ diag
522533 }
523534
524535 /// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +549,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
538549 /// ```
539550 fn report_general_error (
540551 & 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+
553563 let mut diag = infcx. tcx . sess . struct_span_err (
554- span,
564+ * span,
555565 "lifetime may not live long enough"
556566 ) ;
557567
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) {
567569 "closure"
568570 } else {
569571 "function"
570572 } ;
571573
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+
572579 match ( category, outlived_fr_is_local, fr_is_local) {
573580 ( ConstraintCategory :: Return , true , _) => {
574581 diag. span_label (
575- span,
582+ * span,
576583 format ! (
577584 "{} was supposed to return data with lifetime `{}` but it is returning \
578585 data with lifetime `{}`",
@@ -582,7 +589,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
582589 }
583590 _ => {
584591 diag. span_label (
585- span,
592+ * span,
586593 format ! (
587594 "{}requires that `{}` must outlive `{}`" ,
588595 category. description( ) ,
@@ -593,9 +600,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
593600 }
594601 }
595602
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) ;
597604
598- diag. buffer ( errors_buffer ) ;
605+ diag
599606 }
600607
601608 /// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +711,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
704711 borrow_region,
705712 |r| self . provides_universal_region ( r, borrow_region, outlived_region)
706713 ) ;
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+
709722 ( category, from_closure, span, outlived_fr_name)
710723 }
711724
0 commit comments