@@ -1340,14 +1340,13 @@ fn create_cases<'tcx>(
1340
1340
}
1341
1341
}
1342
1342
1343
- if operation == Operation :: Resume {
1343
+ if operation == Operation :: Resume && point . resume_arg != CTX_ARG . into ( ) {
1344
1344
// Move the resume argument to the destination place of the `Yield` terminator
1345
- let resume_arg = CTX_ARG ;
1346
1345
statements. push ( Statement :: new (
1347
1346
source_info,
1348
1347
StatementKind :: Assign ( Box :: new ( (
1349
1348
point. resume_arg ,
1350
- Rvalue :: Use ( Operand :: Move ( resume_arg . into ( ) ) ) ,
1349
+ Rvalue :: Use ( Operand :: Move ( CTX_ARG . into ( ) ) ) ,
1351
1350
) ) ) ,
1352
1351
) ) ;
1353
1352
}
@@ -1439,7 +1438,10 @@ fn check_field_tys_sized<'tcx>(
1439
1438
}
1440
1439
1441
1440
impl < ' tcx > crate :: MirPass < ' tcx > for StateTransform {
1441
+ #[ instrument( level = "debug" , skip( self , tcx, body) , ret) ]
1442
1442
fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
1443
+ debug ! ( def_id = ?body. source. def_id( ) ) ;
1444
+
1443
1445
let Some ( old_yield_ty) = body. yield_ty ( ) else {
1444
1446
// This only applies to coroutines
1445
1447
return ;
@@ -1518,31 +1520,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1518
1520
cleanup_async_drops ( body) ;
1519
1521
}
1520
1522
1521
- // We also replace the resume argument and insert an `Assign`.
1522
- // This is needed because the resume argument `_2` might be live across a `yield`, in which
1523
- // case there is no `Assign` to it that the transform can turn into a store to the coroutine
1524
- // state. After the yield the slot in the coroutine state would then be uninitialized.
1525
- let resume_local = CTX_ARG ;
1526
- let resume_ty = body. local_decls [ resume_local] . ty ;
1527
- let old_resume_local = replace_local ( resume_local, resume_ty, body, tcx) ;
1528
-
1529
- // When first entering the coroutine, move the resume argument into its old local
1530
- // (which is now a generator interior).
1531
- let source_info = SourceInfo :: outermost ( body. span ) ;
1532
- let stmts = & mut body. basic_blocks_mut ( ) [ START_BLOCK ] . statements ;
1533
- stmts. insert (
1534
- 0 ,
1535
- Statement :: new (
1536
- source_info,
1537
- StatementKind :: Assign ( Box :: new ( (
1538
- old_resume_local. into ( ) ,
1539
- Rvalue :: Use ( Operand :: Move ( resume_local. into ( ) ) ) ,
1540
- ) ) ) ,
1541
- ) ,
1542
- ) ;
1543
-
1544
1523
let always_live_locals = always_storage_live_locals ( body) ;
1545
-
1546
1524
let movable = coroutine_kind. movability ( ) == hir:: Movability :: Movable ;
1547
1525
let liveness_info =
1548
1526
locals_live_across_suspend_points ( tcx, body, & always_live_locals, movable) ;
@@ -1583,6 +1561,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1583
1561
} ;
1584
1562
transform. visit_body ( body) ;
1585
1563
1564
+ // MIR parameters are not explicitly assigned-to when entering the MIR body.
1565
+ // If we want to save their values inside the coroutine state, we need to do so explicitly.
1566
+ let source_info = SourceInfo :: outermost ( body. span ) ;
1567
+ let args_iter = body. args_iter ( ) ;
1568
+ body. basic_blocks . as_mut ( ) [ START_BLOCK ] . statements . splice (
1569
+ 0 ..0 ,
1570
+ args_iter. filter_map ( |local| {
1571
+ let ( ty, variant_index, idx) = transform. remap [ local] ?;
1572
+ let lhs = transform. make_field ( variant_index, idx, ty) ;
1573
+ let rhs = Rvalue :: Use ( Operand :: Move ( local. into ( ) ) ) ;
1574
+ let assign = StatementKind :: Assign ( Box :: new ( ( lhs, rhs) ) ) ;
1575
+ Some ( Statement :: new ( source_info, assign) )
1576
+ } ) ,
1577
+ ) ;
1578
+
1586
1579
// Update our MIR struct to reflect the changes we've made
1587
1580
body. arg_count = 2 ; // self, resume arg
1588
1581
body. spread_arg = None ;
0 commit comments