@@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
2424use rustc_abi:: FieldIdx ;
2525use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2626use rustc_data_structures:: graph:: dominators:: Dominators ;
27+ use rustc_data_structures:: unord:: UnordMap ;
2728use rustc_errors:: LintDiagnostic ;
2829use rustc_hir as hir;
2930use rustc_hir:: CRATE_HIR_ID ;
@@ -263,6 +264,7 @@ fn do_mir_borrowck<'tcx>(
263264 regioncx : & regioncx,
264265 used_mut : Default :: default ( ) ,
265266 used_mut_upvars : SmallVec :: new ( ) ,
267+ local_from_upvars : UnordMap :: default ( ) ,
266268 borrow_set : & borrow_set,
267269 upvars : & [ ] ,
268270 local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -288,6 +290,11 @@ fn do_mir_borrowck<'tcx>(
288290 promoted_mbcx. report_move_errors ( ) ;
289291 }
290292
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+ }
291298 let mut mbcx = MirBorrowckCtxt {
292299 infcx : & infcx,
293300 body,
@@ -302,6 +309,7 @@ fn do_mir_borrowck<'tcx>(
302309 regioncx : & regioncx,
303310 used_mut : Default :: default ( ) ,
304311 used_mut_upvars : SmallVec :: new ( ) ,
312+ local_from_upvars,
305313 borrow_set : & borrow_set,
306314 upvars : tcx. closure_captures ( def) ,
307315 local_names,
@@ -557,6 +565,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
557565 /// If the function we're checking is a closure, then we'll need to report back the list of
558566 /// mutable upvars that have been used. This field keeps track of them.
559567 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 > ,
560571 /// Region inference context. This contains the results from region inference and lets us e.g.
561572 /// find out which CFG points are contained in each borrow region.
562573 regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2289,10 +2300,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22892300 // If the local may have been initialized, and it is now currently being
22902301 // mutated, then it is justified to be annotated with the `mut`
22912302 // 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+ }
22962309 }
22972310 }
22982311 RootPlace {
@@ -2310,6 +2323,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
23102323 projection : place_projection,
23112324 } ) {
23122325 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) ;
23132328 }
23142329 }
23152330 }
0 commit comments