@@ -1055,11 +1055,37 @@ fn create_generator_resume_function<'tcx>(
1055
1055
body : & mut BodyAndCache < ' tcx > ,
1056
1056
can_return : bool ,
1057
1057
) {
1058
+ let can_unwind = can_unwind ( tcx, body) ;
1059
+
1058
1060
// Poison the generator when it unwinds
1059
- for block in body. basic_blocks_mut ( ) {
1060
- let source_info = block. terminator ( ) . source_info ;
1061
- if let & TerminatorKind :: Resume = & block. terminator ( ) . kind {
1062
- block. statements . push ( transform. set_discr ( VariantIdx :: new ( POISONED ) , source_info) ) ;
1061
+ if can_unwind {
1062
+ let poison_block = BasicBlock :: new ( body. basic_blocks ( ) . len ( ) ) ;
1063
+ let source_info = source_info ( body) ;
1064
+ body. basic_blocks_mut ( ) . push ( BasicBlockData {
1065
+ statements : vec ! [ transform. set_discr( VariantIdx :: new( POISONED ) , source_info) ] ,
1066
+ terminator : Some ( Terminator { source_info, kind : TerminatorKind :: Resume } ) ,
1067
+ is_cleanup : true ,
1068
+ } ) ;
1069
+
1070
+ for ( idx, block) in body. basic_blocks_mut ( ) . iter_enumerated_mut ( ) {
1071
+ let source_info = block. terminator ( ) . source_info ;
1072
+
1073
+ if let TerminatorKind :: Resume = block. terminator ( ) . kind {
1074
+ // An existing `Resume` terminator is redirected to jump to our dedicated
1075
+ // "poisoning block" above.
1076
+ if idx != poison_block {
1077
+ * block. terminator_mut ( ) = Terminator {
1078
+ source_info,
1079
+ kind : TerminatorKind :: Goto { target : poison_block } ,
1080
+ } ;
1081
+ }
1082
+ } else if !block. is_cleanup {
1083
+ // Any terminators that *can* unwind but don't have an unwind target set are also
1084
+ // pointed at our poisoning block (unless they're part of the cleanup path).
1085
+ if let Some ( unwind @ None ) = block. terminator_mut ( ) . unwind_mut ( ) {
1086
+ * unwind = Some ( poison_block) ;
1087
+ }
1088
+ }
1063
1089
}
1064
1090
}
1065
1091
@@ -1080,7 +1106,7 @@ fn create_generator_resume_function<'tcx>(
1080
1106
) ;
1081
1107
}
1082
1108
1083
- if can_unwind ( tcx , body ) {
1109
+ if can_unwind {
1084
1110
cases. insert (
1085
1111
2 ,
1086
1112
( POISONED , insert_panic_block ( tcx, body, ResumedAfterPanic ( generator_kind) ) ) ,
0 commit comments