@@ -23,6 +23,7 @@ use std::ops::Deref;
23
23
use rustc_abi:: FieldIdx ;
24
24
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
25
25
use rustc_data_structures:: graph:: dominators:: Dominators ;
26
+ use rustc_data_structures:: unord:: UnordMap ;
26
27
use rustc_errors:: Diag ;
27
28
use rustc_hir as hir;
28
29
use rustc_hir:: def_id:: LocalDefId ;
@@ -281,6 +282,7 @@ fn do_mir_borrowck<'tcx>(
281
282
regioncx : & regioncx,
282
283
used_mut : Default :: default ( ) ,
283
284
used_mut_upvars : SmallVec :: new ( ) ,
285
+ local_from_upvars : UnordMap :: default ( ) ,
284
286
borrow_set : & borrow_set,
285
287
upvars : & [ ] ,
286
288
local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -306,6 +308,11 @@ fn do_mir_borrowck<'tcx>(
306
308
}
307
309
}
308
310
311
+ let mut local_from_upvars = UnordMap :: default ( ) ;
312
+ for ( field, & local) in body. local_upvar_map . iter_enumerated ( ) {
313
+ let Some ( local) = local else { continue } ;
314
+ local_from_upvars. insert ( local, field) ;
315
+ }
309
316
let mut mbcx = MirBorrowckCtxt {
310
317
infcx : & infcx,
311
318
param_env,
@@ -321,6 +328,7 @@ fn do_mir_borrowck<'tcx>(
321
328
regioncx : & regioncx,
322
329
used_mut : Default :: default ( ) ,
323
330
used_mut_upvars : SmallVec :: new ( ) ,
331
+ local_from_upvars,
324
332
borrow_set : & borrow_set,
325
333
upvars : tcx. closure_captures ( def) ,
326
334
local_names,
@@ -556,6 +564,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
556
564
/// If the function we're checking is a closure, then we'll need to report back the list of
557
565
/// mutable upvars that have been used. This field keeps track of them.
558
566
used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
567
+ /// Since upvars are moved to real locals, we need to map mutations to the locals back to
568
+ /// the upvars, so that used_mut_upvars is up-to-date.
569
+ local_from_upvars : UnordMap < Local , FieldIdx > ,
559
570
/// Region inference context. This contains the results from region inference and lets us e.g.
560
571
/// find out which CFG points are contained in each borrow region.
561
572
regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2214,10 +2225,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2214
2225
// If the local may have been initialized, and it is now currently being
2215
2226
// mutated, then it is justified to be annotated with the `mut`
2216
2227
// keyword, since the mutation may be a possible reassignment.
2217
- if is_local_mutation_allowed != LocalMutationIsAllowed :: Yes
2218
- && self . is_local_ever_initialized ( local, state) . is_some ( )
2219
- {
2220
- self . used_mut . insert ( local) ;
2228
+ if !matches ! ( is_local_mutation_allowed, LocalMutationIsAllowed :: Yes ) {
2229
+ if self . is_local_ever_initialized ( local, state) . is_some ( ) {
2230
+ self . used_mut . insert ( local) ;
2231
+ } else if let Some ( & field) = self . local_from_upvars . get ( & local) {
2232
+ self . used_mut_upvars . push ( field) ;
2233
+ }
2221
2234
}
2222
2235
}
2223
2236
RootPlace {
@@ -2235,6 +2248,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2235
2248
projection : place_projection,
2236
2249
} ) {
2237
2250
self . used_mut_upvars . push ( field) ;
2251
+ } else if let Some ( & field) = self . local_from_upvars . get ( & place_local) {
2252
+ self . used_mut_upvars . push ( field) ;
2238
2253
}
2239
2254
}
2240
2255
}
0 commit comments