@@ -43,7 +43,7 @@ use std::mem;
43
43
use std:: rc:: Rc ;
44
44
use syntax:: ast;
45
45
use syntax:: attr:: AttrMetaMethods ;
46
- use syntax_pos:: { MultiSpan , Span } ;
46
+ use syntax_pos:: { MultiSpan , Span , BytePos } ;
47
47
use errors:: DiagnosticBuilder ;
48
48
49
49
use rustc:: hir;
@@ -566,7 +566,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
566
566
#[ derive( PartialEq ) ]
567
567
pub enum bckerr_code {
568
568
err_mutbl,
569
- err_out_of_scope( ty:: Region , ty:: Region ) , // superscope, subscope
569
+ err_out_of_scope( ty:: Region , ty:: Region , euv :: LoanCause ) , // superscope, subscope, loan cause
570
570
err_borrowed_pointer_too_short( ty:: Region , ty:: Region ) , // loan, ptr
571
571
}
572
572
@@ -614,9 +614,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
614
614
pub fn report ( & self , err : BckError < ' tcx > ) {
615
615
// Catch and handle some particular cases.
616
616
match ( & err. code , & err. cause ) {
617
- ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReStatic ) ,
617
+ ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReStatic , _ ) ,
618
618
& BorrowViolation ( euv:: ClosureCapture ( span) ) ) |
619
- ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReFree ( ..) ) ,
619
+ ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReFree ( ..) , _ ) ,
620
620
& BorrowViolation ( euv:: ClosureCapture ( span) ) ) => {
621
621
return self . report_out_of_scope_escaping_closure_capture ( & err, span) ;
622
622
}
@@ -963,6 +963,24 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
963
963
. emit ( ) ;
964
964
}
965
965
966
+ fn convert_region_to_span ( & self , region : ty:: Region ) -> Option < Span > {
967
+ match region {
968
+ ty:: ReScope ( scope) => {
969
+ match scope. span ( & self . tcx . region_maps , & self . tcx . map ) {
970
+ Some ( s) => {
971
+ let mut last_span = s;
972
+ last_span. lo = BytePos ( last_span. hi . 0 - 1 ) ;
973
+ Some ( last_span)
974
+ }
975
+ None => {
976
+ None
977
+ }
978
+ }
979
+ }
980
+ _ => None
981
+ }
982
+ }
983
+
966
984
pub fn note_and_explain_bckerr ( & self , db : & mut DiagnosticBuilder , err : BckError < ' tcx > ,
967
985
error_span : Span ) {
968
986
let code = err. code ;
@@ -1003,19 +1021,61 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
1003
1021
}
1004
1022
}
1005
1023
1006
- err_out_of_scope( super_scope, sub_scope) => {
1007
- self . tcx . note_and_explain_region (
1008
- db,
1009
- "reference must be valid for " ,
1010
- sub_scope,
1011
- "..." ) ;
1012
- self . tcx . note_and_explain_region (
1013
- db,
1014
- "...but borrowed value is only valid for " ,
1015
- super_scope,
1016
- "" ) ;
1024
+ err_out_of_scope( super_scope, sub_scope, cause) => {
1025
+ match cause {
1026
+ euv:: ClosureCapture ( s) => {
1027
+ match db. span . primary_span ( ) {
1028
+ Some ( primary) => {
1029
+ db. span = MultiSpan :: from_span ( s) ;
1030
+ db. span_label ( primary, & format ! ( "capture occurs here" ) ) ;
1031
+ db. span_label ( s, & format ! ( "does not live long enough" ) ) ;
1032
+ }
1033
+ None => ( )
1034
+ }
1035
+ }
1036
+ _ => {
1037
+ db. span_label ( error_span, & format ! ( "does not live long enough" ) ) ;
1038
+ }
1039
+ }
1040
+
1041
+ let sub_span = self . convert_region_to_span ( sub_scope) ;
1042
+ let super_span = self . convert_region_to_span ( super_scope) ;
1043
+
1044
+ match ( sub_span, super_span) {
1045
+ ( Some ( s1) , Some ( s2) ) if s1 == s2 => {
1046
+ db. span_label ( s1, & "borrowed value dropped before borrower" ) ;
1047
+ db. note ( "values in a scope are dropped in the opposite order \
1048
+ they are created") ;
1049
+ }
1050
+ _ => {
1051
+ match sub_span {
1052
+ Some ( s) => {
1053
+ db. span_label ( s, & "borrowed value must be valid until here" ) ;
1054
+ }
1055
+ None => {
1056
+ self . tcx . note_and_explain_region (
1057
+ db,
1058
+ "borrowed value must be valid for " ,
1059
+ sub_scope,
1060
+ "..." ) ;
1061
+ }
1062
+ }
1063
+ match super_span {
1064
+ Some ( s) => {
1065
+ db. span_label ( s, & "borrowed value only valid until here" ) ;
1066
+ }
1067
+ None => {
1068
+ self . tcx . note_and_explain_region (
1069
+ db,
1070
+ "...but borrowed value is only valid for " ,
1071
+ super_scope,
1072
+ "" ) ;
1073
+ }
1074
+ }
1075
+ }
1076
+ }
1077
+
1017
1078
if let Some ( span) = statement_scope_span ( self . tcx , super_scope) {
1018
- db. span_label ( error_span, & format ! ( "does not live long enough" ) ) ;
1019
1079
db. span_help ( span,
1020
1080
"consider using a `let` binding to increase its lifetime" ) ;
1021
1081
}
0 commit comments