@@ -66,9 +66,9 @@ use std::mem;
6666use crate :: transform:: { MirPass , MirSource } ;
6767use crate :: transform:: simplify;
6868use crate :: transform:: no_landing_pads:: no_landing_pads;
69- use crate :: dataflow:: { DataflowResults , DataflowResultsConsumer , FlowAtLocation , FlowAtLocationOwned } ;
69+ use crate :: dataflow:: { DataflowResults , DataflowResultsConsumer , FlowAtLocation } ;
7070use crate :: dataflow:: { do_dataflow, DebugFormatted , state_for_location} ;
71- use crate :: dataflow:: { MaybeStorageLive , HaveBeenBorrowedLocals } ;
71+ use crate :: dataflow:: { MaybeStorageLive , HaveBeenBorrowedLocals , RequiresStorage } ;
7272use crate :: util:: dump_mir;
7373use crate :: util:: liveness;
7474
@@ -437,16 +437,17 @@ fn locals_live_across_suspend_points(
437437
438438 // Calculate the MIR locals which have been previously
439439 // 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] ) ) ;
450451
451452 // Calculate the liveness of MIR locals ignoring borrows.
452453 let mut live_locals = liveness:: LiveVarSet :: new_empty ( body. local_decls . len ( ) ) ;
@@ -471,10 +472,10 @@ fn locals_live_across_suspend_points(
471472 statement_index : data. statements . len ( ) ,
472473 } ;
473474
474- if let Some ( ( ref analysis , ref result ) ) = borrowed_locals {
475+ if !movable {
475476 let borrowed_locals = state_for_location ( loc,
476- analysis ,
477- result ,
477+ & borrowed_locals_analysis ,
478+ & borrowed_locals_result ,
478479 body) ;
479480 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
480481 // This is correct for movable generators since borrows cannot live across
@@ -489,34 +490,42 @@ fn locals_live_across_suspend_points(
489490 liveness. outs [ block] . union ( & borrowed_locals) ;
490491 }
491492
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) ;
496497
497498 // Store the storage liveness for later use so we can restore the state
498499 // after a suspension point
499500 storage_liveness_map. insert ( block, storage_liveness. clone ( ) ) ;
500501
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 ) ;
503509
504510 // Locals live are live at this point only if they are used across
505511 // 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 ;
508514 live_locals_here. intersect ( & liveness. outs [ block] ) ;
509515
510516 // The generator argument is ignored
511517 live_locals_here. remove ( self_arg ( ) ) ;
512518
519+ debug ! ( "loc = {:?}, live_locals_here = {:?}" , loc, live_locals_here) ;
520+
513521 // Add the locals live at this suspension point to the set of locals which live across
514522 // any suspension points
515523 live_locals. union ( & live_locals_here) ;
516524
517525 live_locals_at_suspension_points. push ( live_locals_here) ;
518526 }
519527 }
528+ debug ! ( "live_locals = {:?}" , live_locals) ;
520529
521530 // Renumber our liveness_map bitsets to include only the locals we are
522531 // saving.
@@ -627,7 +636,7 @@ struct StorageConflictVisitor<'body, 'tcx, 's> {
627636impl < ' body , ' tcx , ' s > DataflowResultsConsumer < ' body , ' tcx >
628637 for StorageConflictVisitor < ' body , ' tcx , ' s >
629638{
630- type FlowState = FlowAtLocationOwned < ' tcx , MaybeStorageLive < ' body , ' tcx > > ;
639+ type FlowState = FlowAtLocation < ' tcx , MaybeStorageLive < ' body , ' tcx > > ;
631640
632641 fn body ( & self ) -> & ' body Body < ' tcx > {
633642 self . body
@@ -657,7 +666,7 @@ impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx>
657666
658667impl < ' body , ' tcx , ' s > StorageConflictVisitor < ' body , ' tcx , ' s > {
659668 fn apply_state ( & mut self ,
660- flow_state : & FlowAtLocationOwned < ' tcx , MaybeStorageLive < ' body , ' tcx > > ,
669+ flow_state : & FlowAtLocation < ' tcx , MaybeStorageLive < ' body , ' tcx > > ,
661670 loc : Location ) {
662671 // Ignore unreachable blocks.
663672 match self . body . basic_blocks ( ) [ loc. block ] . terminator ( ) . kind {
0 commit comments