@@ -1169,8 +1169,72 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
1169
1169
err. emit ( ) ;
1170
1170
}
1171
1171
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
+
1172
1236
fn report_conflicting_borrow ( & mut self ,
1173
- _context : Context ,
1237
+ context : Context ,
1174
1238
common_prefix : & Lvalue ,
1175
1239
( lvalue, span) : ( & Lvalue , Span ) ,
1176
1240
gen_borrow_kind : BorrowKind ,
@@ -1183,38 +1247,60 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
1183
1247
1184
1248
let issued_span = self . retrieve_borrow_span ( issued_borrow) ;
1185
1249
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
+
1186
1257
// FIXME: supply non-"" `opt_via` when appropriate
1187
1258
let mut err = match ( gen_borrow_kind, "immutable" , "mutable" ,
1188
1259
issued_borrow. kind , "immutable" , "mutable" ) {
1189
1260
( BorrowKind :: Shared , lft, _, BorrowKind :: Mut , _, rgt) |
1190
1261
( BorrowKind :: Mut , _, lft, BorrowKind :: Shared , rgt, _) =>
1191
1262
self . tcx . cannot_reborrow_already_borrowed (
1192
- span, & self . describe_lvalue ( lvalue ) , "" , lft, issued_span,
1263
+ span, & desc_lvalue , "" , lft, issued_span,
1193
1264
"it" , rgt, "" , end_issued_loan_span, Origin :: Mir ) ,
1194
1265
1195
1266
( BorrowKind :: Mut , _, _, BorrowKind :: Mut , _, _) =>
1196
1267
self . tcx . cannot_mutably_borrow_multiply (
1197
- span, & self . describe_lvalue ( lvalue ) , "" , issued_span,
1268
+ span, & desc_lvalue , "" , issued_span,
1198
1269
"" , end_issued_loan_span, Origin :: Mir ) ,
1199
1270
1200
1271
( BorrowKind :: Unique , _, _, BorrowKind :: Unique , _, _) =>
1201
1272
self . tcx . cannot_uniquely_borrow_by_two_closures (
1202
- span, & self . describe_lvalue ( lvalue ) , issued_span,
1273
+ span, & desc_lvalue , issued_span,
1203
1274
end_issued_loan_span, Origin :: Mir ) ,
1204
1275
1205
1276
( BorrowKind :: Unique , _, _, _, _, _) =>
1206
1277
self . tcx . cannot_uniquely_borrow_by_one_closure (
1207
- span, & self . describe_lvalue ( lvalue ) , "" ,
1278
+ span, & desc_lvalue , "" ,
1208
1279
issued_span, "it" , "" , end_issued_loan_span, Origin :: Mir ) ,
1209
1280
1210
1281
( _, _, _, BorrowKind :: Unique , _, _) =>
1211
1282
self . tcx . cannot_reborrow_already_uniquely_borrowed (
1212
- span, & self . describe_lvalue ( lvalue ) , "it" , "" ,
1283
+ span, & desc_lvalue , "it" , "" ,
1213
1284
issued_span, "" , end_issued_loan_span, Origin :: Mir ) ,
1214
1285
1215
1286
( BorrowKind :: Shared , _, _, BorrowKind :: Shared , _, _) =>
1216
1287
unreachable ! ( ) ,
1217
1288
} ;
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
+
1218
1304
err. emit ( ) ;
1219
1305
}
1220
1306
0 commit comments