@@ -23,6 +23,7 @@ use std::ops::Deref;
2323use consumers:: { BodyWithBorrowckFacts , ConsumerOptions } ;
2424use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
2525use rustc_data_structures:: graph:: dominators:: Dominators ;
26+ use rustc_data_structures:: unord:: UnordMap ;
2627use rustc_errors:: Diag ;
2728use rustc_hir as hir;
2829use rustc_hir:: def_id:: LocalDefId ;
@@ -287,6 +288,7 @@ fn do_mir_borrowck<'tcx>(
287288 regioncx : & regioncx,
288289 used_mut : Default :: default ( ) ,
289290 used_mut_upvars : SmallVec :: new ( ) ,
291+ local_from_upvars : UnordMap :: default ( ) ,
290292 borrow_set : & borrow_set,
291293 upvars : & [ ] ,
292294 local_names : IndexVec :: from_elem ( None , & promoted_body. local_decls ) ,
@@ -313,6 +315,11 @@ fn do_mir_borrowck<'tcx>(
313315 }
314316 }
315317
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+ }
316323 let mut mbcx = MirBorrowckCtxt {
317324 infcx : & infcx,
318325 param_env,
@@ -328,6 +335,7 @@ fn do_mir_borrowck<'tcx>(
328335 regioncx : & regioncx,
329336 used_mut : Default :: default ( ) ,
330337 used_mut_upvars : SmallVec :: new ( ) ,
338+ local_from_upvars,
331339 borrow_set : & borrow_set,
332340 upvars : tcx. closure_captures ( def) ,
333341 local_names,
@@ -563,6 +571,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
563571 /// If the function we're checking is a closure, then we'll need to report back the list of
564572 /// mutable upvars that have been used. This field keeps track of them.
565573 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 > ,
566577 /// Region inference context. This contains the results from region inference and lets us e.g.
567578 /// find out which CFG points are contained in each borrow region.
568579 regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2218,10 +2229,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22182229 // If the local may have been initialized, and it is now currently being
22192230 // mutated, then it is justified to be annotated with the `mut`
22202231 // 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+ }
22252238 }
22262239 }
22272240 RootPlace {
@@ -2239,6 +2252,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22392252 projection : place_projection,
22402253 } ) {
22412254 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) ;
22422257 }
22432258 }
22442259 }
0 commit comments