@@ -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 ;
@@ -262,6 +263,7 @@ fn do_mir_borrowck<'tcx>(
262263 regioncx : & regioncx,
263264 used_mut : Default :: default ( ) ,
264265 used_mut_upvars : SmallVec :: new ( ) ,
266+ local_from_upvars : UnordMap :: default ( ) ,
265267 borrow_set : & borrow_set,
266268 upvars : & [ ] ,
267269 local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -286,6 +288,11 @@ fn do_mir_borrowck<'tcx>(
286288 promoted_mbcx. report_move_errors ( ) ;
287289 }
288290
291+ let mut local_from_upvars = UnordMap :: default ( ) ;
292+ for ( field, & local) in body. local_upvar_map . iter_enumerated ( ) {
293+ let Some ( local) = local else { continue } ;
294+ local_from_upvars. insert ( local, field) ;
295+ }
289296 let mut mbcx = MirBorrowckCtxt {
290297 infcx : & infcx,
291298 body,
@@ -300,6 +307,7 @@ fn do_mir_borrowck<'tcx>(
300307 regioncx : & regioncx,
301308 used_mut : Default :: default ( ) ,
302309 used_mut_upvars : SmallVec :: new ( ) ,
310+ local_from_upvars,
303311 borrow_set : & borrow_set,
304312 upvars : tcx. closure_captures ( def) ,
305313 local_names,
@@ -554,6 +562,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
554562 /// If the function we're checking is a closure, then we'll need to report back the list of
555563 /// mutable upvars that have been used. This field keeps track of them.
556564 used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
565+ /// Since upvars are moved to real locals, we need to map mutations to the locals back to
566+ /// the upvars, so that used_mut_upvars is up-to-date.
567+ local_from_upvars : UnordMap < Local , FieldIdx > ,
557568 /// Region inference context. This contains the results from region inference and lets us e.g.
558569 /// find out which CFG points are contained in each borrow region.
559570 regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2270,10 +2281,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22702281 // If the local may have been initialized, and it is now currently being
22712282 // mutated, then it is justified to be annotated with the `mut`
22722283 // keyword, since the mutation may be a possible reassignment.
2273- if is_local_mutation_allowed != LocalMutationIsAllowed :: Yes
2274- && self . is_local_ever_initialized ( local, state) . is_some ( )
2275- {
2276- self . used_mut . insert ( local) ;
2284+ if !matches ! ( is_local_mutation_allowed, LocalMutationIsAllowed :: Yes ) {
2285+ if self . is_local_ever_initialized ( local, state) . is_some ( ) {
2286+ self . used_mut . insert ( local) ;
2287+ } else if let Some ( & field) = self . local_from_upvars . get ( & local) {
2288+ self . used_mut_upvars . push ( field) ;
2289+ }
22772290 }
22782291 }
22792292 RootPlace {
@@ -2291,6 +2304,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22912304 projection : place_projection,
22922305 } ) {
22932306 self . used_mut_upvars . push ( field) ;
2307+ } else if let Some ( & field) = self . local_from_upvars . get ( & place_local) {
2308+ self . used_mut_upvars . push ( field) ;
22942309 }
22952310 }
22962311 }
0 commit comments