@@ -78,10 +78,15 @@ fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
78
78
rvalue : & Rvalue < ' tcx > ,
79
79
location : Location ,
80
80
) {
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
+ }
85
90
}
86
91
self . super_assign ( lvalue, rvalue, location)
87
92
}
@@ -195,10 +200,9 @@ fn replace_flattened_locals<'tcx>(
195
200
return ;
196
201
}
197
202
198
- let mut fragments = IndexVec :: new ( ) ;
203
+ let mut fragments = IndexVec :: < _ , Option < Vec < _ > > > :: from_elem ( None , & body . local_decls ) ;
199
204
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) ) ;
202
206
}
203
207
debug ! ( ?fragments) ;
204
208
@@ -235,17 +239,17 @@ struct ReplacementVisitor<'tcx, 'll> {
235
239
all_dead_locals : BitSet < Local > ,
236
240
/// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
237
241
/// and deinit statement and debuginfo.
238
- fragments : IndexVec < Local , Vec < ( & ' tcx [ PlaceElem < ' tcx > ] , Local ) > > ,
242
+ fragments : IndexVec < Local , Option < Vec < ( & ' tcx [ PlaceElem < ' tcx > ] , Local ) > > > ,
239
243
patch : MirPatch < ' tcx > ,
240
244
}
241
245
242
246
impl < ' tcx , ' ll > ReplacementVisitor < ' tcx , ' ll > {
243
247
fn gather_debug_info_fragments (
244
248
& self ,
245
249
place : PlaceRef < ' tcx > ,
246
- ) -> Vec < VarDebugInfoFragment < ' tcx > > {
250
+ ) -> Option < Vec < VarDebugInfoFragment < ' tcx > > > {
247
251
let mut fragments = Vec :: new ( ) ;
248
- let parts = & self . fragments [ place. local ] ;
252
+ let Some ( parts) = & self . fragments [ place. local ] else { return None } ;
249
253
for ( proj, replacement_local) in parts {
250
254
if proj. starts_with ( place. projection ) {
251
255
fragments. push ( VarDebugInfoFragment {
@@ -254,7 +258,7 @@ impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> {
254
258
} ) ;
255
259
}
256
260
}
257
- fragments
261
+ Some ( fragments)
258
262
}
259
263
260
264
fn replace_place ( & self , place : PlaceRef < ' tcx > ) -> Option < Place < ' tcx > > {
@@ -276,8 +280,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
276
280
fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
277
281
match statement. kind {
278
282
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] {
281
284
for & ( _, fl) in final_locals {
282
285
self . patch . add_statement ( location, StatementKind :: StorageLive ( fl) ) ;
283
286
}
@@ -286,8 +289,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
286
289
return ;
287
290
}
288
291
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] {
291
293
for & ( _, fl) in final_locals {
292
294
self . patch . add_statement ( location, StatementKind :: StorageDead ( fl) ) ;
293
295
}
@@ -297,9 +299,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
297
299
}
298
300
StatementKind :: Deinit ( box ref place) => {
299
301
if let Some ( local) = place. as_local ( )
300
- && self . all_dead_locals . contains ( local)
302
+ && let Some ( final_locals ) = & self . fragments [ local]
301
303
{
302
- let final_locals = & self . fragments [ local] ;
303
304
for & ( _, fl) in final_locals {
304
305
self . patch . add_statement (
305
306
location,
@@ -313,9 +314,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
313
314
314
315
StatementKind :: Assign ( box ( ref place, Rvalue :: Aggregate ( _, ref operands) ) ) => {
315
316
if let Some ( local) = place. as_local ( )
316
- && self . all_dead_locals . contains ( local)
317
+ && let Some ( final_locals ) = & self . fragments [ local]
317
318
{
318
- let final_locals = & self . fragments [ local] ;
319
319
for & ( projection, fl) in final_locals {
320
320
let & [ PlaceElem :: Field ( index, _) ] = projection else { bug ! ( ) } ;
321
321
let index = index. as_usize ( ) ;
@@ -330,6 +330,48 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
330
330
}
331
331
}
332
332
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
+
333
375
_ => { }
334
376
}
335
377
self . super_statement ( statement, location)
@@ -348,9 +390,8 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
348
390
VarDebugInfoContents :: Place ( ref mut place) => {
349
391
if let Some ( repl) = self . replace_place ( place. as_ref ( ) ) {
350
392
* 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 ( ) ) {
352
394
let ty = place. ty ( self . local_decls , self . tcx ) . ty ;
353
- let fragments = self . gather_debug_info_fragments ( place. as_ref ( ) ) ;
354
395
var_debug_info. value = VarDebugInfoContents :: Composite { ty, fragments } ;
355
396
}
356
397
}
@@ -361,8 +402,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
361
402
if let Some ( repl) = self . replace_place ( fragment. contents . as_ref ( ) ) {
362
403
fragment. contents = repl;
363
404
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
+ {
366
408
new_fragments. extend ( frg. into_iter ( ) . map ( |mut f| {
367
409
f. projection . splice ( 0 ..0 , fragment. projection . iter ( ) . copied ( ) ) ;
368
410
f
0 commit comments