@@ -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,12 @@ 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+ }
323+ debug ! ( ?local_from_upvars, "dxf" ) ;
316324 let mut mbcx = MirBorrowckCtxt {
317325 infcx : & infcx,
318326 param_env,
@@ -328,6 +336,7 @@ fn do_mir_borrowck<'tcx>(
328336 regioncx : & regioncx,
329337 used_mut : Default :: default ( ) ,
330338 used_mut_upvars : SmallVec :: new ( ) ,
339+ local_from_upvars,
331340 borrow_set : & borrow_set,
332341 upvars : tcx. closure_captures ( def) ,
333342 local_names,
@@ -563,6 +572,9 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
563572 /// If the function we're checking is a closure, then we'll need to report back the list of
564573 /// mutable upvars that have been used. This field keeps track of them.
565574 used_mut_upvars : SmallVec < [ FieldIdx ; 8 ] > ,
575+ /// Since upvars are moved to real locals, we need to map mutations to the locals back to
576+ /// the upvars, so that used_mut_upvars is up-to-date.
577+ local_from_upvars : UnordMap < Local , FieldIdx > ,
566578 /// Region inference context. This contains the results from region inference and lets us e.g.
567579 /// find out which CFG points are contained in each borrow region.
568580 regioncx : & ' a RegionInferenceContext < ' tcx > ,
@@ -2218,10 +2230,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22182230 // If the local may have been initialized, and it is now currently being
22192231 // mutated, then it is justified to be annotated with the `mut`
22202232 // 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) ;
2233+ if !matches ! ( is_local_mutation_allowed, LocalMutationIsAllowed :: Yes ) {
2234+ if self . is_local_ever_initialized ( local, state) . is_some ( ) {
2235+ self . used_mut . insert ( local) ;
2236+ } else if let Some ( & field) = self . local_from_upvars . get ( & local) {
2237+ self . used_mut_upvars . push ( field) ;
2238+ }
22252239 }
22262240 }
22272241 RootPlace {
@@ -2239,6 +2253,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
22392253 projection : place_projection,
22402254 } ) {
22412255 self . used_mut_upvars . push ( field) ;
2256+ } else if let Some ( & field) = self . local_from_upvars . get ( & place_local) {
2257+ self . used_mut_upvars . push ( field) ;
22422258 }
22432259 }
22442260 }
0 commit comments