@@ -522,6 +522,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
522
522
}
523
523
524
524
pub fn report ( & self , err : BckError < ' tcx > ) {
525
+ // Catch and handle some particular cases.
526
+ match ( & err. code , & err. cause ) {
527
+ ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReStatic ) , & euv:: ClosureCapture ( span) ) |
528
+ ( & err_out_of_scope( ty:: ReScope ( _) , ty:: ReFree ( ..) ) , & euv:: ClosureCapture ( span) ) => {
529
+ return self . report_out_of_scope_escaping_closure_capture ( & err, span) ;
530
+ }
531
+ _ => { }
532
+ }
533
+
534
+ // General fallback.
525
535
self . span_err (
526
536
err. span ,
527
537
& self . bckerr_to_string ( & err) ) ;
@@ -796,16 +806,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
796
806
format ! ( "{} does not live long enough" , msg)
797
807
}
798
808
err_borrowed_pointer_too_short( ..) => {
799
- let descr = match opt_loan_path ( & err. cmt ) {
800
- Some ( lp) => {
801
- format ! ( "`{}`" , self . loan_path_to_string( & * lp) )
802
- }
803
- None => self . cmt_to_string ( & * err. cmt ) ,
804
- } ;
805
-
809
+ let descr = self . cmt_to_path_or_string ( & err. cmt ) ;
806
810
format ! ( "lifetime of {} is too short to guarantee \
807
- its contents can be safely reborrowed",
808
- descr)
811
+ its contents can be safely reborrowed",
812
+ descr)
809
813
}
810
814
}
811
815
}
@@ -888,6 +892,39 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
888
892
}
889
893
}
890
894
895
+ fn report_out_of_scope_escaping_closure_capture ( & self ,
896
+ err : & BckError < ' tcx > ,
897
+ capture_span : Span )
898
+ {
899
+ let cmt_path_or_string = self . cmt_to_path_or_string ( & err. cmt ) ;
900
+
901
+ span_err ! (
902
+ self . tcx. sess, err. span, E0373 ,
903
+ "closure may outlive the current function, \
904
+ but it borrows {}, \
905
+ which is owned by the current function",
906
+ cmt_path_or_string) ;
907
+
908
+ self . tcx . sess . span_note (
909
+ capture_span,
910
+ & format ! ( "{} is borrowed here" ,
911
+ cmt_path_or_string) ) ;
912
+
913
+ let suggestion =
914
+ match self . tcx . sess . codemap ( ) . span_to_snippet ( err. span ) {
915
+ Ok ( string) => format ! ( "move {}" , string) ,
916
+ Err ( _) => format ! ( "move |<args>| <body>" )
917
+ } ;
918
+
919
+ self . tcx . sess . span_suggestion (
920
+ err. span ,
921
+ & format ! ( "to force the closure to take ownership of {} \
922
+ (and any other referenced variables), \
923
+ use the `move` keyword, as shown:",
924
+ cmt_path_or_string) ,
925
+ suggestion) ;
926
+ }
927
+
891
928
pub fn note_and_explain_bckerr ( & self , err : BckError < ' tcx > ) {
892
929
let code = err. code ;
893
930
match code {
@@ -1035,6 +1072,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
1035
1072
pub fn cmt_to_string ( & self , cmt : & mc:: cmt_ < ' tcx > ) -> String {
1036
1073
cmt. descriptive_string ( self . tcx )
1037
1074
}
1075
+
1076
+ pub fn cmt_to_path_or_string ( & self , cmt : & mc:: cmt < ' tcx > ) -> String {
1077
+ match opt_loan_path ( cmt) {
1078
+ Some ( lp) => format ! ( "`{}`" , self . loan_path_to_string( & lp) ) ,
1079
+ None => self . cmt_to_string ( cmt) ,
1080
+ }
1081
+ }
1038
1082
}
1039
1083
1040
1084
fn is_statement_scope ( tcx : & ty:: ctxt , region : ty:: Region ) -> bool {
0 commit comments