@@ -15,7 +15,7 @@ use rustc::hir::def_id::DefId;
15
15
use rustc:: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
16
16
use rustc:: infer:: InferCtxt ;
17
17
use 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 } ;
19
19
use rustc_data_structures:: indexed_vec:: IndexVec ;
20
20
use rustc_errors:: { Diagnostic , DiagnosticBuilder } ;
21
21
use std:: collections:: VecDeque ;
@@ -347,9 +347,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
347
347
) ;
348
348
349
349
// 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) ) {
353
351
let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
354
352
let nice = NiceRegionError :: new_from_span ( infcx. tcx , span, o, f, Some ( tables) ) ;
355
353
if let Some ( _error_reported) = nice. try_report_from_nll ( ) {
@@ -362,17 +360,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
362
360
self . universal_regions . is_local_free_region ( outlived_fr) ,
363
361
) ;
364
362
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) ;
368
365
match ( category, fr_is_local, outlived_fr_is_local) {
369
366
( ConstraintCategory :: Assignment , true , false ) |
370
367
( 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) ,
373
370
_ =>
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,
376
373
category, span, errors_buffer) ,
377
374
} ;
378
375
}
@@ -383,9 +380,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
383
380
infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
384
381
mir_def_id : DefId ,
385
382
fr : RegionVid ,
386
- fr_region : Option < Region < ' tcx > > ,
387
383
outlived_fr : RegionVid ,
388
- outlived_fr_region : Option < Region < ' tcx > > ,
389
384
category : ConstraintCategory ,
390
385
span : Span ,
391
386
errors_buffer : & mut Vec < Diagnostic > ,
@@ -398,8 +393,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
398
393
399
394
if fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) {
400
395
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 ,
403
397
category, span, errors_buffer) ;
404
398
}
405
399
@@ -439,10 +433,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
439
433
mir_def_id : DefId ,
440
434
fr : RegionVid ,
441
435
fr_is_local : bool ,
442
- fr_region : Option < Region < ' tcx > > ,
443
436
outlived_fr : RegionVid ,
444
437
outlived_fr_is_local : bool ,
445
- outlived_fr_region : Option < Region < ' tcx > > ,
446
438
category : ConstraintCategory ,
447
439
span : Span ,
448
440
errors_buffer : & mut Vec < Diagnostic > ,
@@ -477,7 +469,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
477
469
}
478
470
479
471
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 ,
481
473
) ;
482
474
483
475
diag. buffer ( errors_buffer) ;
@@ -487,11 +479,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
487
479
& self ,
488
480
infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
489
481
diag : & mut DiagnosticBuilder < ' _ > ,
482
+ fr : RegionVid ,
483
+ // We need to pass `fr_name` - computing it again will label it twice.
490
484
fr_name : RegionName ,
491
- fr_region : Option < Region < ' tcx > > ,
492
- outlived_fr_region : Option < Region < ' tcx > > ,
485
+ outlived_fr : RegionVid ,
493
486
) {
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) ) {
495
491
if let Some ( ty:: TyS {
496
492
sty : ty:: TyKind :: Anon ( did, substs) ,
497
493
..
@@ -500,6 +496,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
500
496
. map ( |id| infcx. tcx . return_type_impl_trait ( id) )
501
497
. unwrap_or ( None )
502
498
{
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`.
503
503
let has_static_predicate = {
504
504
let predicates_of = infcx. tcx . predicates_of ( * did) ;
505
505
let bounds = predicates_of. instantiate ( infcx. tcx , substs) ;
@@ -509,7 +509,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
509
509
if let ty:: Predicate :: TypeOutlives ( binder) = predicate {
510
510
if let ty:: OutlivesPredicate (
511
511
_,
512
- RegionKind :: ReStatic
512
+ ty :: RegionKind :: ReStatic
513
513
) = binder. skip_binder ( ) {
514
514
found = true ;
515
515
break ;
@@ -523,33 +523,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
523
523
debug ! ( "add_static_impl_trait_suggestion: has_static_predicate={:?}" ,
524
524
has_static_predicate) ;
525
525
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`.
526
528
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
+ ) ;
539
535
} else {
536
+ // Otherwise, we should suggest adding a constraint on the return type.
540
537
let span = infcx. tcx . def_span ( * did) ;
541
538
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
+ } ;
542
543
diag. span_suggestion (
543
544
span,
544
545
& 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 ,
548
549
) ,
549
- match fr_name {
550
- RegionName :: Named ( name) => format ! ( "{} + {}" , snippet, name) ,
551
- RegionName :: Synthesized ( _) => format ! ( "{} + '_" , snippet) ,
552
- } ,
550
+ format ! ( "{} + {}" , snippet, suggestable_fr_name) ,
553
551
) ;
554
552
}
555
553
}
0 commit comments