@@ -66,9 +66,9 @@ use std::mem;
66
66
use crate :: transform:: { MirPass , MirSource } ;
67
67
use crate :: transform:: simplify;
68
68
use crate :: transform:: no_landing_pads:: no_landing_pads;
69
- use crate :: dataflow:: { DataflowResults , DataflowResultsConsumer , FlowAtLocation , FlowAtLocationOwned } ;
69
+ use crate :: dataflow:: { DataflowResults , DataflowResultsConsumer , FlowAtLocation } ;
70
70
use crate :: dataflow:: { do_dataflow, DebugFormatted , state_for_location} ;
71
- use crate :: dataflow:: { MaybeStorageLive , HaveBeenBorrowedLocals } ;
71
+ use crate :: dataflow:: { MaybeStorageLive , HaveBeenBorrowedLocals , RequiresStorage } ;
72
72
use crate :: util:: dump_mir;
73
73
use crate :: util:: liveness;
74
74
@@ -437,16 +437,17 @@ fn locals_live_across_suspend_points(
437
437
438
438
// Calculate the MIR locals which have been previously
439
439
// borrowed (even if they are still active).
440
- // This is only used for immovable generators.
441
- let borrowed_locals = if !movable {
442
- let analysis = HaveBeenBorrowedLocals :: new ( body) ;
443
- let result =
444
- do_dataflow ( tcx, body, def_id, & [ ] , & dead_unwinds, analysis,
445
- |bd, p| DebugFormatted :: new ( & bd. body ( ) . local_decls [ p] ) ) ;
446
- Some ( ( analysis, result) )
447
- } else {
448
- None
449
- } ;
440
+ let borrowed_locals_analysis = HaveBeenBorrowedLocals :: new ( body) ;
441
+ let borrowed_locals_result =
442
+ do_dataflow ( tcx, body, def_id, & [ ] , & dead_unwinds, borrowed_locals_analysis,
443
+ |bd, p| DebugFormatted :: new ( & bd. body ( ) . local_decls [ p] ) ) ;
444
+
445
+ // Calculate the MIR locals that we actually need to keep storage around
446
+ // for.
447
+ let requires_storage_analysis = RequiresStorage :: new ( body, & borrowed_locals_result) ;
448
+ let requires_storage =
449
+ do_dataflow ( tcx, body, def_id, & [ ] , & dead_unwinds, requires_storage_analysis. clone ( ) ,
450
+ |bd, p| DebugFormatted :: new ( & bd. body ( ) . local_decls [ p] ) ) ;
450
451
451
452
// Calculate the liveness of MIR locals ignoring borrows.
452
453
let mut live_locals = liveness:: LiveVarSet :: new_empty ( body. local_decls . len ( ) ) ;
@@ -471,10 +472,10 @@ fn locals_live_across_suspend_points(
471
472
statement_index : data. statements . len ( ) ,
472
473
} ;
473
474
474
- if let Some ( ( ref analysis , ref result ) ) = borrowed_locals {
475
+ if !movable {
475
476
let borrowed_locals = state_for_location ( loc,
476
- analysis ,
477
- result ,
477
+ & borrowed_locals_analysis ,
478
+ & borrowed_locals_result ,
478
479
body) ;
479
480
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
480
481
// This is correct for movable generators since borrows cannot live across
@@ -489,34 +490,42 @@ fn locals_live_across_suspend_points(
489
490
liveness. outs [ block] . union ( & borrowed_locals) ;
490
491
}
491
492
492
- let mut storage_liveness = state_for_location ( loc,
493
- & storage_live_analysis,
494
- & storage_live,
495
- body) ;
493
+ let storage_liveness = state_for_location ( loc,
494
+ & storage_live_analysis,
495
+ & storage_live,
496
+ body) ;
496
497
497
498
// Store the storage liveness for later use so we can restore the state
498
499
// after a suspension point
499
500
storage_liveness_map. insert ( block, storage_liveness. clone ( ) ) ;
500
501
501
- // Mark locals without storage statements as always having live storage
502
- storage_liveness. union ( & ignored. 0 ) ;
502
+ let mut storage_required = state_for_location ( loc,
503
+ & requires_storage_analysis,
504
+ & requires_storage,
505
+ body) ;
506
+
507
+ // Mark locals without storage statements as always requiring storage
508
+ storage_required. union ( & ignored. 0 ) ;
503
509
504
510
// Locals live are live at this point only if they are used across
505
511
// suspension points (the `liveness` variable)
506
- // and their storage is live (the `storage_liveness ` variable)
507
- let mut live_locals_here = storage_liveness ;
512
+ // and their storage is required (the `storage_required ` variable)
513
+ let mut live_locals_here = storage_required ;
508
514
live_locals_here. intersect ( & liveness. outs [ block] ) ;
509
515
510
516
// The generator argument is ignored
511
517
live_locals_here. remove ( self_arg ( ) ) ;
512
518
519
+ debug ! ( "loc = {:?}, live_locals_here = {:?}" , loc, live_locals_here) ;
520
+
513
521
// Add the locals live at this suspension point to the set of locals which live across
514
522
// any suspension points
515
523
live_locals. union ( & live_locals_here) ;
516
524
517
525
live_locals_at_suspension_points. push ( live_locals_here) ;
518
526
}
519
527
}
528
+ debug ! ( "live_locals = {:?}" , live_locals) ;
520
529
521
530
// Renumber our liveness_map bitsets to include only the locals we are
522
531
// saving.
@@ -627,7 +636,7 @@ struct StorageConflictVisitor<'body, 'tcx, 's> {
627
636
impl < ' body , ' tcx , ' s > DataflowResultsConsumer < ' body , ' tcx >
628
637
for StorageConflictVisitor < ' body , ' tcx , ' s >
629
638
{
630
- type FlowState = FlowAtLocationOwned < ' tcx , MaybeStorageLive < ' body , ' tcx > > ;
639
+ type FlowState = FlowAtLocation < ' tcx , MaybeStorageLive < ' body , ' tcx > > ;
631
640
632
641
fn body ( & self ) -> & ' body Body < ' tcx > {
633
642
self . body
@@ -657,7 +666,7 @@ impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx>
657
666
658
667
impl < ' body , ' tcx , ' s > StorageConflictVisitor < ' body , ' tcx , ' s > {
659
668
fn apply_state ( & mut self ,
660
- flow_state : & FlowAtLocationOwned < ' tcx , MaybeStorageLive < ' body , ' tcx > > ,
669
+ flow_state : & FlowAtLocation < ' tcx , MaybeStorageLive < ' body , ' tcx > > ,
661
670
loc : Location ) {
662
671
// Ignore unreachable blocks.
663
672
match self . body . basic_blocks ( ) [ loc. block ] . terminator ( ) . kind {
0 commit comments