@@ -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,30 @@ 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+ 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+
5781impl < ' tcx > RegionInferenceContext < ' tcx > {
5882 /// Tries to find the best constraint to blame for the fact that
5983 /// `R: from_region`, where `R` is some region that meets
@@ -257,16 +281,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
257281 /// ```
258282 ///
259283 /// 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 ,
262286 body : & Body < ' tcx > ,
263287 upvars : & [ Upvar ] ,
264- infcx : & InferCtxt < ' _ , ' tcx > ,
288+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
265289 mir_def_id : DefId ,
266290 fr : RegionVid ,
267291 outlived_fr : RegionVid ,
268- errors_buffer : & mut Vec < Diagnostic > ,
269- ) {
292+ renctx : & mut RegionErrorNamingCtx ,
293+ ) -> DiagnosticBuilder < ' a > {
270294 debug ! ( "report_error(fr={:?}, outlived_fr={:?})" , fr, outlived_fr) ;
271295
272296 let ( category, _, span) = self . best_blame_constraint ( body, fr, |r| {
@@ -279,8 +303,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
279303 let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
280304 let nice = NiceRegionError :: new_from_span ( infcx, span, o, f, Some ( tables) ) ;
281305 if let Some ( diag) = nice. try_report_from_nll ( ) {
282- diag. buffer ( errors_buffer) ;
283- return ;
306+ return diag;
284307 }
285308 }
286309
@@ -293,45 +316,35 @@ impl<'tcx> RegionInferenceContext<'tcx> {
293316 "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
294317 fr_is_local, outlived_fr_is_local, category
295318 ) ;
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+
296332 match ( category, fr_is_local, outlived_fr_is_local) {
297333 ( 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)
308335 }
309336 ( 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+ }
335348 }
336349
337350 /// We have a constraint `fr1: fr2` that is not satisfied, where
@@ -379,19 +392,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
379392 /// ```
380393 fn report_fnmut_error (
381394 & 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
392405 . tcx
393406 . 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" ) ;
395408
396409 // We should check if the return type of this closure is in fact a closure - in that
397410 // case, we can special case the error further.
@@ -403,11 +416,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
403416 "returns a reference to a captured variable which escapes the closure body"
404417 } ;
405418
406- diag. span_label ( span, message) ;
419+ diag. span_label ( * span, message) ;
407420
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 {
411422 RegionNameSource :: NamedEarlyBoundRegion ( fr_span)
412423 | RegionNameSource :: NamedFreeRegion ( fr_span)
413424 | RegionNameSource :: SynthesizedFreeEnvRegion ( fr_span, _)
@@ -427,7 +438,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
427438 ) ;
428439 diag. note ( "...therefore, they cannot allow references to captured variables to escape" ) ;
429440
430- diag. buffer ( errors_buffer ) ;
441+ diag
431442 }
432443
433444 /// Reports a error specifically for when data is escaping a closure.
@@ -444,20 +455,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
444455 /// ```
445456 fn report_escaping_data_error (
446457 & 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+
457470 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 ) ;
459472 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 ) ;
461474
462475 let escapes_from = match self . universal_regions . defining_ty {
463476 DefiningTy :: Closure ( ..) => "closure" ,
@@ -469,27 +482,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
469482 // Revert to the normal error in these cases.
470483 // Assignments aren't "escapes" in function items.
471484 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" )
473486 || escapes_from == "const"
474487 {
475488 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,
487496 ) ;
488497 }
489498
490499 let mut diag = borrowck_errors:: borrowed_data_escapes_closure (
491500 infcx. tcx ,
492- span,
501+ * span,
493502 escapes_from,
494503 ) ;
495504
@@ -513,12 +522,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
513522 ) ;
514523
515524 diag. span_label (
516- span,
525+ * span,
517526 format ! ( "`{}` escapes the {} body here" , fr_name, escapes_from) ,
518527 ) ;
519528 }
520529
521- diag. buffer ( errors_buffer ) ;
530+ diag
522531 }
523532
524533 /// Reports a region inference error for the general case with named/synthesized lifetimes to
@@ -538,41 +547,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
538547 /// ```
539548 fn report_general_error (
540549 & 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+
553561 let mut diag = infcx. tcx . sess . struct_span_err (
554- span,
562+ * span,
555563 "lifetime may not live long enough"
556564 ) ;
557565
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) {
567567 "closure"
568568 } else {
569569 "function"
570570 } ;
571571
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+
572577 match ( category, outlived_fr_is_local, fr_is_local) {
573578 ( ConstraintCategory :: Return , true , _) => {
574579 diag. span_label (
575- span,
580+ * span,
576581 format ! (
577582 "{} was supposed to return data with lifetime `{}` but it is returning \
578583 data with lifetime `{}`",
@@ -582,7 +587,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
582587 }
583588 _ => {
584589 diag. span_label (
585- span,
590+ * span,
586591 format ! (
587592 "{}requires that `{}` must outlive `{}`" ,
588593 category. description( ) ,
@@ -593,9 +598,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
593598 }
594599 }
595600
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) ;
597602
598- diag. buffer ( errors_buffer ) ;
603+ diag
599604 }
600605
601606 /// Adds a suggestion to errors where a `impl Trait` is returned.
@@ -704,8 +709,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
704709 borrow_region,
705710 |r| self . provides_universal_region ( r, borrow_region, outlived_region)
706711 ) ;
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+
709720 ( category, from_closure, span, outlived_fr_name)
710721 }
711722
0 commit comments