@@ -19,6 +19,7 @@ use rustc::mir::{
19
19
VarBindingForm ,
20
20
} ;
21
21
use rustc:: ty;
22
+ use rustc:: hir;
22
23
use rustc_data_structures:: fx:: FxHashSet ;
23
24
use rustc_data_structures:: sync:: Lrc ;
24
25
use rustc_errors:: { Applicability , DiagnosticBuilder } ;
@@ -462,9 +463,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
462
463
}
463
464
464
465
let mut err = match & self . describe_place ( & borrow. borrowed_place ) {
465
- Some ( _) if self . is_place_thread_local ( root_place) => {
466
- self . report_thread_local_value_does_not_live_long_enough ( drop_span, borrow_span)
467
- }
466
+ Some ( _) if self . is_place_thread_local ( root_place) =>
467
+ self . report_thread_local_value_does_not_live_long_enough ( drop_span, borrow_span) ,
468
468
Some ( name) => self . report_local_value_does_not_live_long_enough (
469
469
context,
470
470
name,
@@ -511,14 +511,50 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
511
511
Origin :: Mir ,
512
512
) ;
513
513
514
- err. span_label ( borrow_span, "borrowed value does not live long enough" ) ;
515
- err. span_label (
516
- drop_span,
517
- format ! ( "`{}` dropped here while still borrowed" , name) ,
518
- ) ;
514
+ let explanation = self . explain_why_borrow_contains_point ( context, borrow, kind_place) ;
515
+ if let Some ( (
516
+ arg_name,
517
+ arg_span,
518
+ return_name,
519
+ return_span,
520
+ ) ) = self . find_name_and_ty_of_values ( ) {
521
+ err. span_label (
522
+ arg_span,
523
+ format ! ( "has lifetime `{}`" , arg_name)
524
+ ) ;
519
525
520
- self . explain_why_borrow_contains_point ( context, borrow, kind_place)
521
- . emit ( self . infcx . tcx , & mut err) ;
526
+ err. span_label (
527
+ return_span,
528
+ format ! (
529
+ "{}has lifetime `{}`" ,
530
+ if arg_name == return_name { "also " } else { "" } ,
531
+ return_name
532
+ )
533
+ ) ;
534
+
535
+ err. span_label (
536
+ borrow_span,
537
+ format ! ( "`{}` would have to be valid for `{}`" , name, return_name) ,
538
+ ) ;
539
+
540
+ err. span_label (
541
+ drop_span,
542
+ format ! ( "but `{}` dropped here while still borrowed" , name) ,
543
+ ) ;
544
+
545
+ if let BorrowExplanation :: MustBeValidFor ( ..) = explanation { } else {
546
+ explanation. emit ( self . infcx . tcx , & mut err) ;
547
+ }
548
+ } else {
549
+ err. span_label ( borrow_span, "borrowed value does not live long enough" ) ;
550
+
551
+ err. span_label (
552
+ drop_span,
553
+ format ! ( "`{}` dropped here while still borrowed" , name) ,
554
+ ) ;
555
+
556
+ explanation. emit ( self . infcx . tcx , & mut err) ;
557
+ }
522
558
523
559
err
524
560
}
@@ -645,6 +681,66 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
645
681
err
646
682
}
647
683
684
+ fn find_name_and_ty_of_values (
685
+ & self ,
686
+ ) -> Option < ( String , Span , String , Span ) > {
687
+ let mir_node_id = self . infcx . tcx . hir . as_local_node_id ( self . mir_def_id ) ?;
688
+ let fn_decl = self . infcx . tcx . hir . fn_decl ( mir_node_id) ?;
689
+
690
+ // If there is one argument and this error is being reported, that means
691
+ // that the lifetime of the borrow could not be made to match the single
692
+ // argument's lifetime. We can highlight it.
693
+ //
694
+ // If there is more than one argument and this error is being reported, that
695
+ // means there must be a self parameter - as otherwise there would be an error
696
+ // from lifetime elision and not this. So we highlight the self parameter.
697
+ let arg = fn_decl. inputs
698
+ . first ( )
699
+ . and_then ( |ty| {
700
+ if let hir:: TyKind :: Rptr (
701
+ hir:: Lifetime { name, span, .. } , ..
702
+ ) = ty. node {
703
+ Some ( ( name, span) )
704
+ } else {
705
+ None
706
+ }
707
+ } ) ;
708
+
709
+ let ret = if let hir:: FunctionRetTy :: Return ( ret_ty) = & fn_decl. output {
710
+ if let hir:: Ty {
711
+ node : hir:: TyKind :: Rptr ( hir:: Lifetime { name, span, .. } , ..) ,
712
+ ..
713
+ } = ret_ty. clone ( ) . into_inner ( ) {
714
+ Some ( ( name, span) )
715
+ } else {
716
+ None
717
+ }
718
+ } else {
719
+ None
720
+ } ;
721
+
722
+ let ( arg_name, arg_span) = arg?;
723
+ let ( return_name, return_span) = ret?;
724
+
725
+ let lifetimes_match = arg_name == return_name;
726
+
727
+ let arg_name = if arg_name. is_elided ( ) {
728
+ "'0" . to_string ( )
729
+ } else {
730
+ format ! ( "{}" , arg_name. ident( ) )
731
+ } ;
732
+
733
+ let return_name = if return_name. is_elided ( ) && lifetimes_match {
734
+ "'0" . to_string ( )
735
+ } else if return_name. is_elided ( ) {
736
+ "'1" . to_string ( )
737
+ } else {
738
+ format ! ( "{}" , return_name. ident( ) )
739
+ } ;
740
+
741
+ Some ( ( arg_name, arg_span, return_name, return_span) )
742
+ }
743
+
648
744
fn get_moved_indexes ( & mut self , context : Context , mpi : MovePathIndex ) -> Vec < MoveOutIndex > {
649
745
let mir = self . mir ;
650
746
0 commit comments