@@ -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) ) ;
@@ -795,16 +805,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
795
805
format ! ( "{} does not live long enough" , msg)
796
806
}
797
807
err_borrowed_pointer_too_short( ..) => {
798
- let descr = match opt_loan_path ( & err. cmt ) {
799
- Some ( lp) => {
800
- format ! ( "`{}`" , self . loan_path_to_string( & * lp) )
801
- }
802
- None => self . cmt_to_string ( & * err. cmt ) ,
803
- } ;
804
-
808
+ let descr = self . cmt_to_path_or_string ( & err. cmt ) ;
805
809
format ! ( "lifetime of {} is too short to guarantee \
806
- its contents can be safely reborrowed",
807
- descr)
810
+ its contents can be safely reborrowed",
811
+ descr)
808
812
}
809
813
}
810
814
}
@@ -886,6 +890,39 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
886
890
}
887
891
}
888
892
893
+ fn report_out_of_scope_escaping_closure_capture ( & self ,
894
+ err : & BckError < ' tcx > ,
895
+ capture_span : Span )
896
+ {
897
+ let cmt_path_or_string = self . cmt_to_path_or_string ( & err. cmt ) ;
898
+
899
+ span_err ! (
900
+ self . tcx. sess, err. span, E0371 ,
901
+ "closure may outlive the current function, \
902
+ but it borrows {}, \
903
+ which is owned by the current function",
904
+ cmt_path_or_string) ;
905
+
906
+ self . tcx . sess . span_note (
907
+ capture_span,
908
+ & format ! ( "{} is borrowed here" ,
909
+ cmt_path_or_string) ) ;
910
+
911
+ let suggestion =
912
+ match self . tcx . sess . codemap ( ) . span_to_snippet ( err. span ) {
913
+ Ok ( string) => format ! ( "move {}" , string. lines( ) . next( ) . unwrap( ) ) ,
914
+ Err ( _) => format ! ( "move |<args>| <body>" )
915
+ } ;
916
+
917
+ self . tcx . sess . span_suggestion (
918
+ err. span ,
919
+ & format ! ( "to force the closure to take ownership of {} \
920
+ (and any other referenced variables), \
921
+ use the `move` keyword, as shown:",
922
+ cmt_path_or_string) ,
923
+ suggestion) ;
924
+ }
925
+
889
926
pub fn note_and_explain_bckerr ( & self , err : BckError < ' tcx > ) {
890
927
let code = err. code ;
891
928
match code {
@@ -1033,6 +1070,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
1033
1070
pub fn cmt_to_string ( & self , cmt : & mc:: cmt_ < ' tcx > ) -> String {
1034
1071
cmt. descriptive_string ( self . tcx )
1035
1072
}
1073
+
1074
+ pub fn cmt_to_path_or_string ( & self , cmt : & mc:: cmt < ' tcx > ) -> String {
1075
+ match opt_loan_path ( cmt) {
1076
+ Some ( lp) => format ! ( "`{}`" , self . loan_path_to_string( & lp) ) ,
1077
+ None => self . cmt_to_string ( cmt) ,
1078
+ }
1079
+ }
1036
1080
}
1037
1081
1038
1082
fn is_statement_scope ( tcx : & ty:: ctxt , region : ty:: Region ) -> bool {
0 commit comments