@@ -1169,8 +1169,70 @@ 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 aclosure (within `maybe_closure_span`) and its usage of
1173+ /// the local assigned at `location`.
1174+ fn find_closure_span (
1175+ & self ,
1176+ maybe_closure_span : Span ,
1177+ location : Location ,
1178+ ) -> Option < ( Span , Span ) > {
1179+ use rustc:: hir:: ExprClosure ;
1180+ use rustc:: mir:: AggregateKind ;
1181+
1182+ let local = if let StatementKind :: Assign ( Lvalue :: Local ( local) , _) =
1183+ self . mir [ location. block ] . statements [ location. statement_index ] . kind
1184+ {
1185+ local
1186+ } else {
1187+ return None ;
1188+ } ;
1189+
1190+ for stmt in & self . mir [ location. block ] . statements [ location. statement_index + 1 ..] {
1191+ if maybe_closure_span != stmt. source_info . span {
1192+ break ;
1193+ }
1194+
1195+ if let StatementKind :: Assign ( _, Rvalue :: Aggregate ( ref kind, ref lvs) ) = stmt. kind {
1196+ if let AggregateKind :: Closure ( def_id, _) = * * kind {
1197+ debug ! ( "find_closure_span: found closure {:?}" , lvs) ;
1198+
1199+ return if let Some ( node_id) = self . tcx . hir . as_local_node_id ( def_id) {
1200+ let args_span = if let ExprClosure ( _, _, _, span, _) =
1201+ self . tcx . hir . expect_expr ( node_id) . node
1202+ {
1203+ span
1204+ } else {
1205+ return None ;
1206+ } ;
1207+
1208+ self . tcx
1209+ . with_freevars ( node_id, |freevars| {
1210+ for ( v, lv) in freevars. iter ( ) . zip ( lvs) {
1211+ if let Operand :: Consume ( Lvalue :: Local ( l) ) = * lv {
1212+ if local == l {
1213+ debug ! (
1214+ "find_closure_span: found captured local {:?}" ,
1215+ l
1216+ ) ;
1217+ return Some ( v. span ) ;
1218+ }
1219+ }
1220+ }
1221+ None
1222+ } )
1223+ . map ( |var_span| ( args_span, var_span) )
1224+ } else {
1225+ None
1226+ } ;
1227+ }
1228+ }
1229+ }
1230+
1231+ None
1232+ }
1233+
11721234 fn report_conflicting_borrow ( & mut self ,
1173- _context : Context ,
1235+ context : Context ,
11741236 common_prefix : & Lvalue ,
11751237 ( lvalue, span) : ( & Lvalue , Span ) ,
11761238 gen_borrow_kind : BorrowKind ,
@@ -1183,38 +1245,60 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
11831245
11841246 let issued_span = self . retrieve_borrow_span ( issued_borrow) ;
11851247
1248+ let new_closure_span = self . find_closure_span ( span, context. loc ) ;
1249+ let span = new_closure_span. map ( |( args, _) | args) . unwrap_or ( span) ;
1250+ let old_closure_span = self . find_closure_span ( issued_span, issued_borrow. location ) ;
1251+ let issued_span = old_closure_span. map ( |( args, _) | args) . unwrap_or ( issued_span) ;
1252+
1253+ let desc_lvalue = self . describe_lvalue ( lvalue) ;
1254+
11861255 // FIXME: supply non-"" `opt_via` when appropriate
11871256 let mut err = match ( gen_borrow_kind, "immutable" , "mutable" ,
11881257 issued_borrow. kind , "immutable" , "mutable" ) {
11891258 ( BorrowKind :: Shared , lft, _, BorrowKind :: Mut , _, rgt) |
11901259 ( BorrowKind :: Mut , _, lft, BorrowKind :: Shared , rgt, _) =>
11911260 self . tcx . cannot_reborrow_already_borrowed (
1192- span, & self . describe_lvalue ( lvalue ) , "" , lft, issued_span,
1261+ span, & desc_lvalue , "" , lft, issued_span,
11931262 "it" , rgt, "" , end_issued_loan_span, Origin :: Mir ) ,
11941263
11951264 ( BorrowKind :: Mut , _, _, BorrowKind :: Mut , _, _) =>
11961265 self . tcx . cannot_mutably_borrow_multiply (
1197- span, & self . describe_lvalue ( lvalue ) , "" , issued_span,
1266+ span, & desc_lvalue , "" , issued_span,
11981267 "" , end_issued_loan_span, Origin :: Mir ) ,
11991268
12001269 ( BorrowKind :: Unique , _, _, BorrowKind :: Unique , _, _) =>
12011270 self . tcx . cannot_uniquely_borrow_by_two_closures (
1202- span, & self . describe_lvalue ( lvalue ) , issued_span,
1271+ span, & desc_lvalue , issued_span,
12031272 end_issued_loan_span, Origin :: Mir ) ,
12041273
12051274 ( BorrowKind :: Unique , _, _, _, _, _) =>
12061275 self . tcx . cannot_uniquely_borrow_by_one_closure (
1207- span, & self . describe_lvalue ( lvalue ) , "" ,
1276+ span, & desc_lvalue , "" ,
12081277 issued_span, "it" , "" , end_issued_loan_span, Origin :: Mir ) ,
12091278
12101279 ( _, _, _, BorrowKind :: Unique , _, _) =>
12111280 self . tcx . cannot_reborrow_already_uniquely_borrowed (
1212- span, & self . describe_lvalue ( lvalue ) , "it" , "" ,
1281+ span, & desc_lvalue , "it" , "" ,
12131282 issued_span, "" , end_issued_loan_span, Origin :: Mir ) ,
12141283
12151284 ( BorrowKind :: Shared , _, _, BorrowKind :: Shared , _, _) =>
12161285 unreachable ! ( ) ,
12171286 } ;
1287+
1288+ if let Some ( ( _, var_span) ) = old_closure_span {
1289+ err. span_label (
1290+ var_span,
1291+ format ! ( "previous borrow occurs due to use of `{}` in closure" , desc_lvalue) ,
1292+ ) ;
1293+ }
1294+
1295+ if let Some ( ( _, var_span) ) = new_closure_span {
1296+ err. span_label (
1297+ var_span,
1298+ format ! ( "borrow occurs due to use of `{}` in closure" , desc_lvalue) ,
1299+ ) ;
1300+ }
1301+
12181302 err. emit ( ) ;
12191303 }
12201304
0 commit comments