@@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
24
24
use rustc_abi:: FieldIdx ;
25
25
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
26
26
use rustc_data_structures:: graph:: dominators:: Dominators ;
27
+ use rustc_data_structures:: unord:: UnordMap ;
27
28
use rustc_errors:: LintDiagnostic ;
28
29
use rustc_hir as hir;
29
30
use rustc_hir:: CRATE_HIR_ID ;
@@ -263,6 +264,7 @@ fn do_mir_borrowck<'tcx>(
263
264
regioncx : & regioncx,
264
265
used_mut : Default :: default ( ) ,
265
266
used_mut_upvars : SmallVec :: new ( ) ,
267
+ local_from_upvars : UnordMap :: default ( ) ,
266
268
borrow_set : & borrow_set,
267
269
upvars : & [ ] ,
268
270
local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -288,6 +290,11 @@ fn do_mir_borrowck<'tcx>(
288
290
promoted_mbcx. report_move_errors ( ) ;
289
291
}
290
292
293
+ let mut local_from_upvars = UnordMap :: default ( ) ;
294
+ for ( field, & local) in body. local_upvar_map . iter_enumerated ( ) {
295
+ let Some ( local) = local else { continue } ;
296
+ local_from_upvars. insert ( local, field) ;
297
+ }
291
298
let mut mbcx = MirBorrowckCtxt {
292
299
infcx : & infcx,
293
300
body,
@@ -302,6 +309,7 @@ fn do_mir_borrowck<'tcx>(
302
309
regioncx : & regioncx,
303
310
used_mut : Default :: default ( ) ,
304
311
used_mut_upvars : SmallVec :: new ( ) ,
312
+ local_from_upvars,
305
313
borrow_set : & borrow_set,
306
314
upvars : tcx. closure_captures ( def) ,
307
315
local_names,
@@ -557,6 +565,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
557
565
/// If the function we're checking is a closure, then we'll need to report back the list of
558
566
/// mutable upvars that have been used. This field keeps track of them.
559
567
used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
568
+ /// Since upvars are moved to real locals, we need to map mutations to the locals back to
569
+ /// the upvars, so that used_mut_upvars is up-to-date.
570
+ local_from_upvars : UnordMap < Local , FieldIdx > ,
560
571
/// Region inference context. This contains the results from region inference and lets us e.g.
561
572
/// find out which CFG points are contained in each borrow region.
562
573
regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2289,10 +2300,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2289
2300
// If the local may have been initialized, and it is now currently being
2290
2301
// mutated, then it is justified to be annotated with the `mut`
2291
2302
// keyword, since the mutation may be a possible reassignment.
2292
- if is_local_mutation_allowed != LocalMutationIsAllowed :: Yes
2293
- && self . is_local_ever_initialized ( local, state) . is_some ( )
2294
- {
2295
- self . used_mut . insert ( local) ;
2303
+ if !matches ! ( is_local_mutation_allowed, LocalMutationIsAllowed :: Yes ) {
2304
+ if self . is_local_ever_initialized ( local, state) . is_some ( ) {
2305
+ self . used_mut . insert ( local) ;
2306
+ } else if let Some ( & field) = self . local_from_upvars . get ( & local) {
2307
+ self . used_mut_upvars . push ( field) ;
2308
+ }
2296
2309
}
2297
2310
}
2298
2311
RootPlace {
@@ -2310,6 +2323,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
2310
2323
projection : place_projection,
2311
2324
} ) {
2312
2325
self . used_mut_upvars . push ( field) ;
2326
+ } else if let Some ( & field) = self . local_from_upvars . get ( & place_local) {
2327
+ self . used_mut_upvars . push ( field) ;
2313
2328
}
2314
2329
}
2315
2330
}
0 commit comments