@@ -78,10 +78,15 @@ fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
7878 rvalue : & Rvalue < ' tcx > ,
7979 location : Location ,
8080 ) {
81- if lvalue. as_local ( ) . is_some ( ) && let Rvalue :: Aggregate ( ..) = rvalue {
82- // Aggregate assignments are expanded in run_pass.
83- self . visit_rvalue ( rvalue, location) ;
84- return ;
81+ if lvalue. as_local ( ) . is_some ( ) {
82+ match rvalue {
83+ // Aggregate assignments are expanded in run_pass.
84+ Rvalue :: Aggregate ( ..) | Rvalue :: Use ( ..) => {
85+ self . visit_rvalue ( rvalue, location) ;
86+ return ;
87+ }
88+ _ => { }
89+ }
8590 }
8691 self . super_assign ( lvalue, rvalue, location)
8792 }
@@ -195,10 +200,9 @@ fn replace_flattened_locals<'tcx>(
195200 return ;
196201 }
197202
198- let mut fragments = IndexVec :: new ( ) ;
203+ let mut fragments = IndexVec :: < _ , Option < Vec < _ > > > :: from_elem ( None , & body . local_decls ) ;
199204 for ( k, v) in & replacements. fields {
200- fragments. ensure_contains_elem ( k. local , || Vec :: new ( ) ) ;
201- fragments[ k. local ] . push ( ( k. projection , * v) ) ;
205+ fragments[ k. local ] . get_or_insert_default ( ) . push ( ( k. projection , * v) ) ;
202206 }
203207 debug ! ( ?fragments) ;
204208
@@ -235,17 +239,17 @@ struct ReplacementVisitor<'tcx, 'll> {
235239 all_dead_locals : BitSet < Local > ,
236240 /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
237241 /// and deinit statement and debuginfo.
238- fragments : IndexVec < Local , Vec < ( & ' tcx [ PlaceElem < ' tcx > ] , Local ) > > ,
242+ fragments : IndexVec < Local , Option < Vec < ( & ' tcx [ PlaceElem < ' tcx > ] , Local ) > > > ,
239243 patch : MirPatch < ' tcx > ,
240244}
241245
242246impl < ' tcx , ' ll > ReplacementVisitor < ' tcx , ' ll > {
243247 fn gather_debug_info_fragments (
244248 & self ,
245249 place : PlaceRef < ' tcx > ,
246- ) -> Vec < VarDebugInfoFragment < ' tcx > > {
250+ ) -> Option < Vec < VarDebugInfoFragment < ' tcx > > > {
247251 let mut fragments = Vec :: new ( ) ;
248- let parts = & self . fragments [ place. local ] ;
252+ let Some ( parts) = & self . fragments [ place. local ] else { return None } ;
249253 for ( proj, replacement_local) in parts {
250254 if proj. starts_with ( place. projection ) {
251255 fragments. push ( VarDebugInfoFragment {
@@ -254,7 +258,7 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> {
254258 } ) ;
255259 }
256260 }
257- fragments
261+ Some ( fragments)
258262 }
259263
260264 fn replace_place ( & self , place : PlaceRef < ' tcx > ) -> Option < Place < ' tcx > > {
@@ -276,8 +280,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
276280 fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
277281 match statement. kind {
278282 StatementKind :: StorageLive ( l) => {
279- if self . all_dead_locals . contains ( l) {
280- let final_locals = & self . fragments [ l] ;
283+ if let Some ( final_locals) = & self . fragments [ l] {
281284 for & ( _, fl) in final_locals {
282285 self . patch . add_statement ( location, StatementKind :: StorageLive ( fl) ) ;
283286 }
@@ -286,8 +289,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
286289 return ;
287290 }
288291 StatementKind :: StorageDead ( l) => {
289- if self . all_dead_locals . contains ( l) {
290- let final_locals = & self . fragments [ l] ;
292+ if let Some ( final_locals) = & self . fragments [ l] {
291293 for & ( _, fl) in final_locals {
292294 self . patch . add_statement ( location, StatementKind :: StorageDead ( fl) ) ;
293295 }
@@ -297,9 +299,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
297299 }
298300 StatementKind :: Deinit ( box ref place) => {
299301 if let Some ( local) = place. as_local ( )
300- && self . all_dead_locals . contains ( local)
302+ && let Some ( final_locals ) = & self . fragments [ local]
301303 {
302- let final_locals = & self . fragments [ local] ;
303304 for & ( _, fl) in final_locals {
304305 self . patch . add_statement (
305306 location,
@@ -313,9 +314,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
313314
314315 StatementKind :: Assign ( box ( ref place, Rvalue :: Aggregate ( _, ref operands) ) ) => {
315316 if let Some ( local) = place. as_local ( )
316- && self . all_dead_locals . contains ( local)
317+ && let Some ( final_locals ) = & self . fragments [ local]
317318 {
318- let final_locals = & self . fragments [ local] ;
319319 for & ( projection, fl) in final_locals {
320320 let & [ PlaceElem :: Field ( index, _) ] = projection else { bug ! ( ) } ;
321321 let index = index. as_usize ( ) ;
@@ -330,6 +330,48 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
330330 }
331331 }
332332
333+ StatementKind :: Assign ( box ( ref place, Rvalue :: Use ( Operand :: Constant ( _) ) ) ) => {
334+ if let Some ( local) = place. as_local ( )
335+ && let Some ( final_locals) = & self . fragments [ local]
336+ {
337+ for & ( projection, fl) in final_locals {
338+ let rvalue = Rvalue :: Use ( Operand :: Move ( place. project_deeper ( projection, self . tcx ) ) ) ;
339+ self . patch . add_statement (
340+ location,
341+ StatementKind :: Assign ( Box :: new ( ( fl. into ( ) , rvalue) ) ) ,
342+ ) ;
343+ }
344+ self . all_dead_locals . remove ( local) ;
345+ return ;
346+ }
347+ }
348+
349+ StatementKind :: Assign ( box ( ref lhs, Rvalue :: Use ( ref op) ) ) => {
350+ let ( rplace, copy) = match op {
351+ Operand :: Copy ( rplace) => ( rplace, true ) ,
352+ Operand :: Move ( rplace) => ( rplace, false ) ,
353+ Operand :: Constant ( _) => bug ! ( ) ,
354+ } ;
355+ if let Some ( local) = lhs. as_local ( )
356+ && let Some ( final_locals) = & self . fragments [ local]
357+ {
358+ for & ( projection, fl) in final_locals {
359+ let rplace = rplace. project_deeper ( projection, self . tcx ) ;
360+ let rvalue = if copy {
361+ Rvalue :: Use ( Operand :: Copy ( rplace) )
362+ } else {
363+ Rvalue :: Use ( Operand :: Move ( rplace) )
364+ } ;
365+ self . patch . add_statement (
366+ location,
367+ StatementKind :: Assign ( Box :: new ( ( fl. into ( ) , rvalue) ) ) ,
368+ ) ;
369+ }
370+ statement. make_nop ( ) ;
371+ return ;
372+ }
373+ }
374+
333375 _ => { }
334376 }
335377 self . super_statement ( statement, location)
@@ -348,9 +390,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
348390 VarDebugInfoContents :: Place ( ref mut place) => {
349391 if let Some ( repl) = self . replace_place ( place. as_ref ( ) ) {
350392 * place = repl;
351- } else if self . all_dead_locals . contains ( place. local ) {
393+ } else if let Some ( fragments ) = self . gather_debug_info_fragments ( place. as_ref ( ) ) {
352394 let ty = place. ty ( self . local_decls , self . tcx ) . ty ;
353- let fragments = self . gather_debug_info_fragments ( place. as_ref ( ) ) ;
354395 var_debug_info. value = VarDebugInfoContents :: Composite { ty, fragments } ;
355396 }
356397 }
@@ -361,8 +402,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
361402 if let Some ( repl) = self . replace_place ( fragment. contents . as_ref ( ) ) {
362403 fragment. contents = repl;
363404 true
364- } else if self . all_dead_locals . contains ( fragment. contents . local ) {
365- let frg = self . gather_debug_info_fragments ( fragment. contents . as_ref ( ) ) ;
405+ } else if let Some ( frg) =
406+ self . gather_debug_info_fragments ( fragment. contents . as_ref ( ) )
407+ {
366408 new_fragments. extend ( frg. into_iter ( ) . map ( |mut f| {
367409 f. projection . splice ( 0 ..0 , fragment. projection . iter ( ) . copied ( ) ) ;
368410 f
0 commit comments