2626//! }
2727//!
2828//! This pass computes the meaning of the state field and the MIR locals which are live
29- //! across a suspension point. There are however two hardcoded generator states:
29+ //! across a suspension point. There are however three hardcoded generator states:
3030//! 0 - Generator have not been resumed yet
3131//! 1 - Generator has returned / is completed
3232//! 2 - Generator has been poisoned
@@ -144,6 +144,13 @@ fn self_arg() -> Local {
144144 Local :: new ( 1 )
145145}
146146
147+ /// Generator have not been resumed yet
148+ const UNRESUMED : u32 = 0 ;
149+ /// Generator has returned / is completed
150+ const RETURNED : u32 = 1 ;
151+ /// Generator has been poisoned
152+ const POISONED : u32 = 2 ;
153+
147154struct SuspensionPoint {
148155 state : u32 ,
149156 resume : BasicBlock ,
@@ -278,7 +285,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
278285
279286 state
280287 } else { // Return
281- 1 // state for returned
288+ RETURNED // state for returned
282289 } ;
283290 data. statements . push ( self . set_state ( state, source_info) ) ;
284291 data. terminator . as_mut ( ) . unwrap ( ) . kind = TerminatorKind :: Return ;
@@ -590,8 +597,15 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
590597 let param_env = tcx. param_env ( def_id) ;
591598 let gen = self_arg ( ) ;
592599
593- for block in mir. basic_blocks ( ) . indices ( ) {
594- let ( target, unwind, source_info) = match mir. basic_blocks ( ) [ block] . terminator ( ) {
600+ let mut elaborator = DropShimElaborator {
601+ mir : mir,
602+ patch : MirPatch :: new ( mir) ,
603+ tcx,
604+ param_env
605+ } ;
606+
607+ for ( block, block_data) in mir. basic_blocks ( ) . iter_enumerated ( ) {
608+ let ( target, unwind, source_info) = match block_data. terminator ( ) {
595609 & Terminator {
596610 source_info,
597611 kind : TerminatorKind :: Drop {
@@ -602,31 +616,22 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
602616 } if local == gen => ( target, unwind, source_info) ,
603617 _ => continue ,
604618 } ;
605- let unwind = if let Some ( unwind) = unwind {
606- Unwind :: To ( unwind)
607- } else {
619+ let unwind = if block_data. is_cleanup {
608620 Unwind :: InCleanup
621+ } else {
622+ Unwind :: To ( unwind. unwrap_or_else ( || elaborator. patch . resume_block ( ) ) )
609623 } ;
610- let patch = {
611- let mut elaborator = DropShimElaborator {
612- mir : & mir,
613- patch : MirPatch :: new ( mir) ,
614- tcx,
615- param_env
616- } ;
617- elaborate_drop (
618- & mut elaborator,
619- source_info,
620- & Place :: Base ( PlaceBase :: Local ( gen) ) ,
621- ( ) ,
622- target,
623- unwind,
624- block
625- ) ;
626- elaborator. patch
627- } ;
628- patch. apply ( mir) ;
624+ elaborate_drop (
625+ & mut elaborator,
626+ source_info,
627+ & Place :: Base ( PlaceBase :: Local ( gen) ) ,
628+ ( ) ,
629+ target,
630+ unwind,
631+ block,
632+ ) ;
629633 }
634+ elaborator. patch . apply ( mir) ;
630635}
631636
632637fn create_generator_drop_shim < ' a , ' tcx > (
@@ -643,10 +648,10 @@ fn create_generator_drop_shim<'a, 'tcx>(
643648
644649 let mut cases = create_cases ( & mut mir, transform, |point| point. drop ) ;
645650
646- cases. insert ( 0 , ( 0 , drop_clean) ) ;
651+ cases. insert ( 0 , ( UNRESUMED , drop_clean) ) ;
647652
648- // The returned state (1) and the poisoned state (2) falls through to
649- // the default case which is just to return
653+ // The returned state and the poisoned state fall through to the default
654+ // case which is just to return
650655
651656 insert_switch ( tcx, & mut mir, cases, & transform, TerminatorKind :: Return ) ;
652657
@@ -762,7 +767,7 @@ fn create_generator_resume_function<'a, 'tcx>(
762767 for block in mir. basic_blocks_mut ( ) {
763768 let source_info = block. terminator ( ) . source_info ;
764769 if let & TerminatorKind :: Resume = & block. terminator ( ) . kind {
765- block. statements . push ( transform. set_state ( 1 , source_info) ) ;
770+ block. statements . push ( transform. set_state ( POISONED , source_info) ) ;
766771 }
767772 }
768773
@@ -773,12 +778,12 @@ fn create_generator_resume_function<'a, 'tcx>(
773778 GeneratorResumedAfterReturn ,
774779 } ;
775780
776- // Jump to the entry point on the 0 state
777- cases. insert ( 0 , ( 0 , BasicBlock :: new ( 0 ) ) ) ;
778- // Panic when resumed on the returned (1) state
779- cases. insert ( 1 , ( 1 , insert_panic_block ( tcx, mir, GeneratorResumedAfterReturn ) ) ) ;
780- // Panic when resumed on the poisoned (2) state
781- cases. insert ( 2 , ( 2 , insert_panic_block ( tcx, mir, GeneratorResumedAfterPanic ) ) ) ;
781+ // Jump to the entry point on the unresumed
782+ cases. insert ( 0 , ( UNRESUMED , BasicBlock :: new ( 0 ) ) ) ;
783+ // Panic when resumed on the returned state
784+ cases. insert ( 1 , ( RETURNED , insert_panic_block ( tcx, mir, GeneratorResumedAfterReturn ) ) ) ;
785+ // Panic when resumed on the poisoned state
786+ cases. insert ( 2 , ( POISONED , insert_panic_block ( tcx, mir, GeneratorResumedAfterPanic ) ) ) ;
782787
783788 insert_switch ( tcx, mir, cases, & transform, TerminatorKind :: Unreachable ) ;
784789
@@ -942,7 +947,7 @@ impl MirPass for StateTransform {
942947 mir. generator_layout = Some ( layout) ;
943948
944949 // Insert `drop(generator_struct)` which is used to drop upvars for generators in
945- // the unresumed (0) state.
950+ // the unresumed state.
946951 // This is expanded to a drop ladder in `elaborate_generator_drops`.
947952 let drop_clean = insert_clean_drop ( mir) ;
948953
0 commit comments