@@ -15,7 +15,7 @@ use rustc::hir::def_id::DefId;
1515use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
1616use rustc:: infer:: InferCtxt ;
1717use rustc:: mir:: { self , Location , Mir , Place , Rvalue , StatementKind , TerminatorKind } ;
18- use rustc:: ty:: { self , TyCtxt , Region , RegionKind , RegionVid } ;
18+ use rustc:: ty:: { self , TyCtxt , RegionVid } ;
1919use rustc_data_structures:: indexed_vec:: IndexVec ;
2020use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
2121use std:: collections:: VecDeque ;
@@ -347,9 +347,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
347347 ) ;
348348
349349 // Check if we can use one of the "nice region errors".
350- let fr_region = self . to_error_region ( fr) ;
351- let outlived_fr_region = self . to_error_region ( outlived_fr) ;
352- if let ( Some ( f) , Some ( o) ) = ( fr_region, outlived_fr_region) {
350+ if let ( Some ( f) , Some ( o) ) = ( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) ) {
353351 let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
354352 let nice = NiceRegionError :: new_from_span ( infcx. tcx , span, o, f, Some ( tables) ) ;
355353 if let Some ( _error_reported) = nice. try_report_from_nll ( ) {
@@ -362,17 +360,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
362360 self . universal_regions . is_local_free_region ( outlived_fr) ,
363361 ) ;
364362
365- debug ! ( "report_error: fr_is_local={:?} outlived_fr_is_local={:?} fr_region={:?} \
366- outlived_fr_region={:?} category={:?}",
367- fr_is_local, outlived_fr_is_local, fr_region, outlived_fr_region, category) ;
363+ debug ! ( "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
364+ fr_is_local, outlived_fr_is_local, category) ;
368365 match ( category, fr_is_local, outlived_fr_is_local) {
369366 ( ConstraintCategory :: Assignment , true , false ) |
370367 ( ConstraintCategory :: CallArgument , true , false ) =>
371- self . report_escaping_data_error ( mir, infcx, mir_def_id, fr, fr_region , outlived_fr,
372- outlived_fr_region , category, span, errors_buffer) ,
368+ self . report_escaping_data_error ( mir, infcx, mir_def_id, fr, outlived_fr,
369+ category, span, errors_buffer) ,
373370 _ =>
374- self . report_general_error ( mir, infcx, mir_def_id, fr, fr_is_local, fr_region ,
375- outlived_fr, outlived_fr_is_local, outlived_fr_region ,
371+ self . report_general_error ( mir, infcx, mir_def_id, fr, fr_is_local,
372+ outlived_fr, outlived_fr_is_local,
376373 category, span, errors_buffer) ,
377374 } ;
378375 }
@@ -383,9 +380,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
383380 infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
384381 mir_def_id : DefId ,
385382 fr : RegionVid ,
386- fr_region : Option < Region < ' tcx > > ,
387383 outlived_fr : RegionVid ,
388- outlived_fr_region : Option < Region < ' tcx > > ,
389384 category : ConstraintCategory ,
390385 span : Span ,
391386 errors_buffer : & mut Vec < Diagnostic > ,
@@ -398,8 +393,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
398393
399394 if fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) {
400395 return self . report_general_error ( mir, infcx, mir_def_id,
401- fr, true , fr_region,
402- outlived_fr, false , outlived_fr_region,
396+ fr, true , outlived_fr, false ,
403397 category, span, errors_buffer) ;
404398 }
405399
@@ -439,10 +433,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
439433 mir_def_id : DefId ,
440434 fr : RegionVid ,
441435 fr_is_local : bool ,
442- fr_region : Option < Region < ' tcx > > ,
443436 outlived_fr : RegionVid ,
444437 outlived_fr_is_local : bool ,
445- outlived_fr_region : Option < Region < ' tcx > > ,
446438 category : ConstraintCategory ,
447439 span : Span ,
448440 errors_buffer : & mut Vec < Diagnostic > ,
@@ -477,7 +469,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
477469 }
478470
479471 self . add_static_impl_trait_suggestion (
480- infcx, & mut diag, fr_name , fr_region , outlived_fr_region
472+ infcx, & mut diag, fr , fr_name , outlived_fr ,
481473 ) ;
482474
483475 diag. buffer ( errors_buffer) ;
@@ -487,11 +479,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
487479 & self ,
488480 infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
489481 diag : & mut DiagnosticBuilder < ' _ > ,
482+ fr : RegionVid ,
483+ // We need to pass `fr_name` - computing it again will label it twice.
490484 fr_name : RegionName ,
491- fr_region : Option < Region < ' tcx > > ,
492- outlived_fr_region : Option < Region < ' tcx > > ,
485+ outlived_fr : RegionVid ,
493486 ) {
494- if let ( Some ( f) , Some ( ty:: RegionKind :: ReStatic ) ) = ( fr_region, outlived_fr_region) {
487+ if let (
488+ Some ( f) ,
489+ Some ( ty:: RegionKind :: ReStatic )
490+ ) = ( self . to_error_region ( fr) , self . to_error_region ( outlived_fr) ) {
495491 if let Some ( ty:: TyS {
496492 sty : ty:: TyKind :: Anon ( did, substs) ,
497493 ..
@@ -500,6 +496,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
500496 . map ( |id| infcx. tcx . return_type_impl_trait ( id) )
501497 . unwrap_or ( None )
502498 {
499+ // Check whether or not the impl trait return type is intended to capture
500+ // data with the static lifetime.
501+ //
502+ // eg. check for `impl Trait + 'static` instead of `impl Trait`.
503503 let has_static_predicate = {
504504 let predicates_of = infcx. tcx . predicates_of ( * did) ;
505505 let bounds = predicates_of. instantiate ( infcx. tcx , substs) ;
@@ -509,7 +509,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
509509 if let ty:: Predicate :: TypeOutlives ( binder) = predicate {
510510 if let ty:: OutlivesPredicate (
511511 _,
512- RegionKind :: ReStatic
512+ ty :: RegionKind :: ReStatic
513513 ) = binder. skip_binder ( ) {
514514 found = true ;
515515 break ;
@@ -523,33 +523,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
523523 debug ! ( "add_static_impl_trait_suggestion: has_static_predicate={:?}" ,
524524 has_static_predicate) ;
525525 let static_str = keywords:: StaticLifetime . name ( ) ;
526+ // If there is a static predicate, then the only sensible suggestion is to replace
527+ // fr with `'static`.
526528 if has_static_predicate {
527- let span = self . get_span_of_named_region ( infcx. tcx , f, & fr_name) ;
528- if let Ok ( snippet) = infcx. tcx . sess . source_map ( ) . span_to_snippet ( span) {
529- diag. span_suggestion (
530- span,
531- & format ! (
532- "you can add a constraint to the definition of `{}` to require it \
533- outlive `{}`",
534- fr_name, static_str,
535- ) ,
536- format ! ( "{}: {}" , snippet, static_str) ,
537- ) ;
538- }
529+ diag. help (
530+ & format ! (
531+ "consider replacing `{}` with `{}`" ,
532+ fr_name, static_str,
533+ ) ,
534+ ) ;
539535 } else {
536+ // Otherwise, we should suggest adding a constraint on the return type.
540537 let span = infcx. tcx . def_span ( * did) ;
541538 if let Ok ( snippet) = infcx. tcx . sess . source_map ( ) . span_to_snippet ( span) {
539+ let suggestable_fr_name = match fr_name {
540+ RegionName :: Named ( name) => format ! ( "{}" , name) ,
541+ RegionName :: Synthesized ( _) => "'_" . to_string ( ) ,
542+ } ;
542543 diag. span_suggestion (
543544 span,
544545 & format ! (
545- "you can add a constraint to the return type to make it last \
546- less than `{}` and match `{}`",
547- static_str , fr_name ,
546+ "to allow this impl Trait to capture borrowed data with lifetime \
547+ `{}`, add `{}` as a constraint ",
548+ fr_name , suggestable_fr_name ,
548549 ) ,
549- match fr_name {
550- RegionName :: Named ( name) => format ! ( "{} + {}" , snippet, name) ,
551- RegionName :: Synthesized ( _) => format ! ( "{} + '_" , snippet) ,
552- } ,
550+ format ! ( "{} + {}" , snippet, suggestable_fr_name) ,
553551 ) ;
554552 }
555553 }
0 commit comments