@@ -522,6 +522,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
522522 }
523523
524524 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.
525535 self . span_err (
526536 err. span ,
527537 & self . bckerr_to_string ( & err) ) ;
@@ -795,16 +805,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
795805 format ! ( "{} does not live long enough" , msg)
796806 }
797807 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 ) ;
805809 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)
808812 }
809813 }
810814 }
@@ -886,6 +890,39 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
886890 }
887891 }
888892
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, E0372 ,
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+
889926 pub fn note_and_explain_bckerr ( & self , err : BckError < ' tcx > ) {
890927 let code = err. code ;
891928 match code {
@@ -1033,6 +1070,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
10331070 pub fn cmt_to_string ( & self , cmt : & mc:: cmt_ < ' tcx > ) -> String {
10341071 cmt. descriptive_string ( self . tcx )
10351072 }
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+ }
10361080}
10371081
10381082fn is_statement_scope ( tcx : & ty:: ctxt , region : ty:: Region ) -> bool {
0 commit comments