@@ -192,9 +192,10 @@ const RETURNED: usize = GeneratorSubsts::RETURNED;
192
192
/// Generator has been poisoned
193
193
const POISONED : usize = GeneratorSubsts :: POISONED ;
194
194
195
- struct SuspensionPoint {
195
+ struct SuspensionPoint < ' tcx > {
196
196
state : usize ,
197
197
resume : BasicBlock ,
198
+ resume_arg : Place < ' tcx > ,
198
199
drop : Option < BasicBlock > ,
199
200
storage_liveness : liveness:: LiveVarSet ,
200
201
}
@@ -216,7 +217,7 @@ struct TransformVisitor<'tcx> {
216
217
storage_liveness : FxHashMap < BasicBlock , liveness:: LiveVarSet > ,
217
218
218
219
// A list of suspension points, generated during the transform
219
- suspension_points : Vec < SuspensionPoint > ,
220
+ suspension_points : Vec < SuspensionPoint < ' tcx > > ,
220
221
221
222
// The original RETURN_PLACE local
222
223
new_ret_local : Local ,
@@ -303,8 +304,8 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
303
304
Operand :: Move ( Place :: from ( self . new_ret_local ) ) ,
304
305
None ,
305
306
) ) ,
306
- TerminatorKind :: Yield { ref value, resume, drop } => {
307
- Some ( ( VariantIdx :: new ( 0 ) , Some ( resume) , value. clone ( ) , drop) )
307
+ TerminatorKind :: Yield { ref value, resume, resume_arg , drop } => {
308
+ Some ( ( VariantIdx :: new ( 0 ) , Some ( ( resume, resume_arg ) ) , value. clone ( ) , drop) )
308
309
}
309
310
_ => None ,
310
311
} ;
@@ -319,13 +320,14 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
319
320
self . make_state ( state_idx, v) ,
320
321
) ) ,
321
322
} ) ;
322
- let state = if let Some ( resume) = resume {
323
+ let state = if let Some ( ( resume, resume_arg ) ) = resume {
323
324
// Yield
324
325
let state = 3 + self . suspension_points . len ( ) ;
325
326
326
327
self . suspension_points . push ( SuspensionPoint {
327
328
state,
328
329
resume,
330
+ resume_arg,
329
331
drop,
330
332
storage_liveness : self . storage_liveness . get ( & block) . unwrap ( ) . clone ( ) ,
331
333
} ) ;
@@ -1063,7 +1065,7 @@ fn create_cases<'tcx, F>(
1063
1065
target : F ,
1064
1066
) -> Vec < ( usize , BasicBlock ) >
1065
1067
where
1066
- F : Fn ( & SuspensionPoint ) -> Option < BasicBlock > ,
1068
+ F : Fn ( & SuspensionPoint < ' tcx > ) -> Option < BasicBlock > ,
1067
1069
{
1068
1070
let source_info = source_info ( body) ;
1069
1071
@@ -1085,6 +1087,16 @@ where
1085
1087
}
1086
1088
}
1087
1089
1090
+ // Move the resume argument to the destination place of the `Yield` terminator
1091
+ let resume_arg = Local :: new ( 2 ) ; // 0 = return, 1 = self
1092
+ statements. push ( Statement {
1093
+ source_info,
1094
+ kind : StatementKind :: Assign ( box (
1095
+ point. resume_arg ,
1096
+ Rvalue :: Use ( Operand :: Move ( resume_arg. into ( ) ) ) ,
1097
+ ) ) ,
1098
+ } ) ;
1099
+
1088
1100
// Then jump to the real target
1089
1101
body. basic_blocks_mut ( ) . push ( BasicBlockData {
1090
1102
statements,
@@ -1163,7 +1175,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
1163
1175
} ;
1164
1176
transform. visit_body ( body) ;
1165
1177
1166
- // Update our MIR struct to reflect the changed we've made
1178
+ // Update our MIR struct to reflect the changes we've made
1167
1179
body. yield_ty = None ;
1168
1180
body. arg_count = 2 ; // self, resume arg
1169
1181
body. spread_arg = None ;
0 commit comments