@@ -1169,8 +1169,72 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
11691169 err. emit ( ) ;
11701170 }
11711171
1172+ /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
1173+ /// the local assigned at `location`.
1174+ /// This is done by searching in statements succeeding `location`
1175+ /// and originating from `maybe_closure_span`.
1176+ fn find_closure_span (
1177+ & self ,
1178+ maybe_closure_span : Span ,
1179+ location : Location ,
1180+ ) -> Option < ( Span , Span ) > {
1181+ use rustc:: hir:: ExprClosure ;
1182+ use rustc:: mir:: AggregateKind ;
1183+
1184+ let local = if let StatementKind :: Assign ( Lvalue :: Local ( local) , _) =
1185+ self . mir [ location. block ] . statements [ location. statement_index ] . kind
1186+ {
1187+ local
1188+ } else {
1189+ return None ;
1190+ } ;
1191+
1192+ for stmt in & self . mir [ location. block ] . statements [ location. statement_index + 1 ..] {
1193+ if maybe_closure_span != stmt. source_info . span {
1194+ break ;
1195+ }
1196+
1197+ if let StatementKind :: Assign ( _, Rvalue :: Aggregate ( ref kind, ref lvs) ) = stmt. kind {
1198+ if let AggregateKind :: Closure ( def_id, _) = * * kind {
1199+ debug ! ( "find_closure_span: found closure {:?}" , lvs) ;
1200+
1201+ return if let Some ( node_id) = self . tcx . hir . as_local_node_id ( def_id) {
1202+ let args_span = if let ExprClosure ( _, _, _, span, _) =
1203+ self . tcx . hir . expect_expr ( node_id) . node
1204+ {
1205+ span
1206+ } else {
1207+ return None ;
1208+ } ;
1209+
1210+ self . tcx
1211+ . with_freevars ( node_id, |freevars| {
1212+ for ( v, lv) in freevars. iter ( ) . zip ( lvs) {
1213+ if let Operand :: Consume ( Lvalue :: Local ( l) ) = * lv {
1214+ if local == l {
1215+ debug ! (
1216+ "find_closure_span: found captured local {:?}" ,
1217+ l
1218+ ) ;
1219+ return Some ( v. span ) ;
1220+ }
1221+ }
1222+ }
1223+ None
1224+ } )
1225+ . map ( |var_span| ( args_span, var_span) )
1226+ } else {
1227+ None
1228+ } ;
1229+ }
1230+ }
1231+ }
1232+
1233+ None
1234+ }
1235+
11721236 fn report_conflicting_borrow ( & mut self ,
1173- _context : Context ,
1237+ context : Context ,
11741238 common_prefix : & Lvalue ,
11751239 ( lvalue, span) : ( & Lvalue , Span ) ,
11761240 gen_borrow_kind : BorrowKind ,
@@ -1183,38 +1247,60 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
11831247
11841248 let issued_span = self . retrieve_borrow_span ( issued_borrow) ;
11851249
1250+ let new_closure_span = self . find_closure_span ( span, context. loc ) ;
1251+ let span = new_closure_span. map ( |( args, _) | args) . unwrap_or ( span) ;
1252+ let old_closure_span = self . find_closure_span ( issued_span, issued_borrow. location ) ;
1253+ let issued_span = old_closure_span. map ( |( args, _) | args) . unwrap_or ( issued_span) ;
1254+
1255+ let desc_lvalue = self . describe_lvalue ( lvalue) ;
1256+
11861257 // FIXME: supply non-"" `opt_via` when appropriate
11871258 let mut err = match ( gen_borrow_kind, "immutable" , "mutable" ,
11881259 issued_borrow. kind , "immutable" , "mutable" ) {
11891260 ( BorrowKind :: Shared , lft, _, BorrowKind :: Mut , _, rgt) |
11901261 ( BorrowKind :: Mut , _, lft, BorrowKind :: Shared , rgt, _) =>
11911262 self . tcx . cannot_reborrow_already_borrowed (
1192- span, & self . describe_lvalue ( lvalue ) , "" , lft, issued_span,
1263+ span, & desc_lvalue , "" , lft, issued_span,
11931264 "it" , rgt, "" , end_issued_loan_span, Origin :: Mir ) ,
11941265
11951266 ( BorrowKind :: Mut , _, _, BorrowKind :: Mut , _, _) =>
11961267 self . tcx . cannot_mutably_borrow_multiply (
1197- span, & self . describe_lvalue ( lvalue ) , "" , issued_span,
1268+ span, & desc_lvalue , "" , issued_span,
11981269 "" , end_issued_loan_span, Origin :: Mir ) ,
11991270
12001271 ( BorrowKind :: Unique , _, _, BorrowKind :: Unique , _, _) =>
12011272 self . tcx . cannot_uniquely_borrow_by_two_closures (
1202- span, & self . describe_lvalue ( lvalue ) , issued_span,
1273+ span, & desc_lvalue , issued_span,
12031274 end_issued_loan_span, Origin :: Mir ) ,
12041275
12051276 ( BorrowKind :: Unique , _, _, _, _, _) =>
12061277 self . tcx . cannot_uniquely_borrow_by_one_closure (
1207- span, & self . describe_lvalue ( lvalue ) , "" ,
1278+ span, & desc_lvalue , "" ,
12081279 issued_span, "it" , "" , end_issued_loan_span, Origin :: Mir ) ,
12091280
12101281 ( _, _, _, BorrowKind :: Unique , _, _) =>
12111282 self . tcx . cannot_reborrow_already_uniquely_borrowed (
1212- span, & self . describe_lvalue ( lvalue ) , "it" , "" ,
1283+ span, & desc_lvalue , "it" , "" ,
12131284 issued_span, "" , end_issued_loan_span, Origin :: Mir ) ,
12141285
12151286 ( BorrowKind :: Shared , _, _, BorrowKind :: Shared , _, _) =>
12161287 unreachable ! ( ) ,
12171288 } ;
1289+
1290+ if let Some ( ( _, var_span) ) = old_closure_span {
1291+ err. span_label (
1292+ var_span,
1293+ format ! ( "previous borrow occurs due to use of `{}` in closure" , desc_lvalue) ,
1294+ ) ;
1295+ }
1296+
1297+ if let Some ( ( _, var_span) ) = new_closure_span {
1298+ err. span_label (
1299+ var_span,
1300+ format ! ( "borrow occurs due to use of `{}` in closure" , desc_lvalue) ,
1301+ ) ;
1302+ }
1303+
12181304 err. emit ( ) ;
12191305 }
12201306
0 commit comments