@@ -23,6 +23,7 @@ use std::ops::Deref;
23
23
use consumers:: { BodyWithBorrowckFacts , ConsumerOptions } ;
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 ;
@@ -287,6 +288,7 @@ fn do_mir_borrowck<'tcx>(
287
288
regioncx : & regioncx,
288
289
used_mut : Default :: default ( ) ,
289
290
used_mut_upvars : SmallVec :: new ( ) ,
291
+ local_from_upvars : UnordMap :: default ( ) ,
290
292
borrow_set : & borrow_set,
291
293
upvars : & [ ] ,
292
294
local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -313,6 +315,11 @@ fn do_mir_borrowck<'tcx>(
313
315
}
314
316
}
315
317
318
+ let mut local_from_upvars = UnordMap :: default ( ) ;
319
+ for ( field, & local) in body. local_upvar_map . iter_enumerated ( ) {
320
+ let Some ( local) = local else { continue } ;
321
+ local_from_upvars. insert ( local, field) ;
322
+ }
316
323
let mut mbcx = MirBorrowckCtxt {
317
324
infcx : & infcx,
318
325
param_env,
@@ -328,6 +335,7 @@ fn do_mir_borrowck<'tcx>(
328
335
regioncx : & regioncx,
329
336
used_mut : Default :: default ( ) ,
330
337
used_mut_upvars : SmallVec :: new ( ) ,
338
+ local_from_upvars,
331
339
borrow_set : & borrow_set,
332
340
upvars : tcx. closure_captures ( def) ,
333
341
local_names,
@@ -563,6 +571,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
563
571
/// If the function we're checking is a closure, then we'll need to report back the list of
564
572
/// mutable upvars that have been used. This field keeps track of them.
565
573
used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
574
+ /// Since upvars are moved to real locals, we need to map mutations to the locals back to
575
+ /// the upvars, so that used_mut_upvars is up-to-date.
576
+ local_from_upvars : UnordMap < Local , FieldIdx > ,
566
577
/// Region inference context. This contains the results from region inference and lets us e.g.
567
578
/// find out which CFG points are contained in each borrow region.
568
579
regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2218,10 +2229,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2218
2229
// If the local may have been initialized, and it is now currently being
2219
2230
// mutated, then it is justified to be annotated with the `mut`
2220
2231
// keyword, since the mutation may be a possible reassignment.
2221
- if is_local_mutation_allowed != LocalMutationIsAllowed :: Yes
2222
- && self . is_local_ever_initialized ( local, state) . is_some ( )
2223
- {
2224
- self . used_mut . insert ( local) ;
2232
+ if !matches ! ( is_local_mutation_allowed, LocalMutationIsAllowed :: Yes ) {
2233
+ if self . is_local_ever_initialized ( local, state) . is_some ( ) {
2234
+ self . used_mut . insert ( local) ;
2235
+ } else if let Some ( & field) = self . local_from_upvars . get ( & local) {
2236
+ self . used_mut_upvars . push ( field) ;
2237
+ }
2225
2238
}
2226
2239
}
2227
2240
RootPlace {
@@ -2239,6 +2252,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2239
2252
projection : place_projection,
2240
2253
} ) {
2241
2254
self . used_mut_upvars . push ( field) ;
2255
+ } else if let Some ( & field) = self . local_from_upvars . get ( & place_local) {
2256
+ self . used_mut_upvars . push ( field) ;
2242
2257
}
2243
2258
}
2244
2259
}
0 commit comments