@@ -211,6 +211,9 @@ struct TransformVisitor<'tcx> {
211
211
old_yield_ty : Ty < ' tcx > ,
212
212
213
213
old_ret_ty : Ty < ' tcx > ,
214
+
215
+ /// The rvalue that should be assigned to yield `resume_arg` place.
216
+ resume_rvalue : Rvalue < ' tcx > ,
214
217
}
215
218
216
219
impl < ' tcx > TransformVisitor < ' tcx > {
@@ -533,100 +536,6 @@ fn replace_local<'tcx>(
533
536
new_local
534
537
}
535
538
536
- /// Transforms the `body` of the coroutine applying the following transforms:
537
- ///
538
- /// - Eliminates all the `get_context` calls that async lowering created.
539
- /// - Replace all `Local` `ResumeTy` types with `&mut Context<'_>` (`context_mut_ref`).
540
- ///
541
- /// The `Local`s that have their types replaced are:
542
- /// - The `resume` argument itself.
543
- /// - The argument to `get_context`.
544
- /// - The yielded value of a `yield`.
545
- ///
546
- /// The `ResumeTy` hides a `&mut Context<'_>` behind an unsafe raw pointer, and the
547
- /// `get_context` function is being used to convert that back to a `&mut Context<'_>`.
548
- ///
549
- /// Ideally the async lowering would not use the `ResumeTy`/`get_context` indirection,
550
- /// but rather directly use `&mut Context<'_>`, however that would currently
551
- /// lead to higher-kinded lifetime errors.
552
- /// See <https://github.com/rust-lang/rust/issues/105501>.
553
- ///
554
- /// The async lowering step and the type / lifetime inference / checking are
555
- /// still using the `ResumeTy` indirection for the time being, and that indirection
556
- /// is removed here. After this transform, the coroutine body only knows about `&mut Context<'_>`.
557
- fn transform_async_context < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) -> Ty < ' tcx > {
558
- let context_mut_ref = Ty :: new_task_context ( tcx) ;
559
-
560
- // replace the type of the `resume` argument
561
- replace_resume_ty_local ( tcx, body, CTX_ARG , context_mut_ref) ;
562
-
563
- let get_context_def_id = tcx. require_lang_item ( LangItem :: GetContext , body. span ) ;
564
-
565
- for bb in body. basic_blocks . indices ( ) {
566
- let bb_data = & body[ bb] ;
567
- if bb_data. is_cleanup {
568
- continue ;
569
- }
570
-
571
- match & bb_data. terminator ( ) . kind {
572
- TerminatorKind :: Call { func, .. } => {
573
- let func_ty = func. ty ( body, tcx) ;
574
- if let ty:: FnDef ( def_id, _) = * func_ty. kind ( )
575
- && def_id == get_context_def_id
576
- {
577
- let local = eliminate_get_context_call ( & mut body[ bb] ) ;
578
- replace_resume_ty_local ( tcx, body, local, context_mut_ref) ;
579
- }
580
- }
581
- TerminatorKind :: Yield { resume_arg, .. } => {
582
- replace_resume_ty_local ( tcx, body, resume_arg. local , context_mut_ref) ;
583
- }
584
- _ => { }
585
- }
586
- }
587
- context_mut_ref
588
- }
589
-
590
- fn eliminate_get_context_call < ' tcx > ( bb_data : & mut BasicBlockData < ' tcx > ) -> Local {
591
- let terminator = bb_data. terminator . take ( ) . unwrap ( ) ;
592
- let TerminatorKind :: Call { args, destination, target, .. } = terminator. kind else {
593
- bug ! ( ) ;
594
- } ;
595
- let [ arg] = * Box :: try_from ( args) . unwrap ( ) ;
596
- let local = arg. node . place ( ) . unwrap ( ) . local ;
597
-
598
- let arg = Rvalue :: Use ( arg. node ) ;
599
- let assign =
600
- Statement :: new ( terminator. source_info , StatementKind :: Assign ( Box :: new ( ( destination, arg) ) ) ) ;
601
- bb_data. statements . push ( assign) ;
602
- bb_data. terminator = Some ( Terminator {
603
- source_info : terminator. source_info ,
604
- kind : TerminatorKind :: Goto { target : target. unwrap ( ) } ,
605
- } ) ;
606
- local
607
- }
608
-
609
- #[ cfg_attr( not( debug_assertions) , allow( unused) ) ]
610
- fn replace_resume_ty_local < ' tcx > (
611
- tcx : TyCtxt < ' tcx > ,
612
- body : & mut Body < ' tcx > ,
613
- local : Local ,
614
- context_mut_ref : Ty < ' tcx > ,
615
- ) {
616
- let local_ty = std:: mem:: replace ( & mut body. local_decls [ local] . ty , context_mut_ref) ;
617
- // We have to replace the `ResumeTy` that is used for type and borrow checking
618
- // with `&mut Context<'_>` in MIR.
619
- #[ cfg( debug_assertions) ]
620
- {
621
- if let ty:: Adt ( resume_ty_adt, _) = local_ty. kind ( ) {
622
- let expected_adt = tcx. adt_def ( tcx. require_lang_item ( LangItem :: ResumeTy , body. span ) ) ;
623
- assert_eq ! ( * resume_ty_adt, expected_adt) ;
624
- } else {
625
- panic ! ( "expected `ResumeTy`, found `{:?}`" , local_ty) ;
626
- } ;
627
- }
628
- }
629
-
630
539
/// Transforms the `body` of the coroutine applying the following transform:
631
540
///
632
541
/// - Remove the `resume` argument.
@@ -1342,12 +1251,11 @@ fn create_cases<'tcx>(
1342
1251
1343
1252
if operation == Operation :: Resume {
1344
1253
// Move the resume argument to the destination place of the `Yield` terminator
1345
- let resume_arg = CTX_ARG ;
1346
1254
statements. push ( Statement :: new (
1347
1255
source_info,
1348
1256
StatementKind :: Assign ( Box :: new ( (
1349
1257
point. resume_arg ,
1350
- Rvalue :: Use ( Operand :: Move ( resume_arg . into ( ) ) ) ,
1258
+ transform . resume_rvalue . clone ( ) ,
1351
1259
) ) ) ,
1352
1260
) ) ;
1353
1261
}
@@ -1504,12 +1412,8 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1504
1412
) && has_expandable_async_drops ( tcx, body, coroutine_ty) ;
1505
1413
1506
1414
// Replace all occurrences of `ResumeTy` with `&mut Context<'_>` within async bodies.
1507
- if matches ! (
1508
- coroutine_kind,
1509
- CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _)
1510
- ) {
1511
- let context_mut_ref = transform_async_context ( tcx, body) ;
1512
- expand_async_drops ( tcx, body, context_mut_ref, coroutine_kind, coroutine_ty) ;
1415
+ if has_async_drops {
1416
+ expand_async_drops ( tcx, body, coroutine_kind, coroutine_ty) ;
1513
1417
1514
1418
if let Some ( dumper) = MirDumper :: new ( tcx, "coroutine_async_drop_expand" , body) {
1515
1419
dumper. dump_mir ( body) ;
@@ -1522,22 +1426,27 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1522
1426
// This is needed because the resume argument `_2` might be live across a `yield`, in which
1523
1427
// case there is no `Assign` to it that the transform can turn into a store to the coroutine
1524
1428
// 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) ;
1429
+ let resume_ty = body. local_decls [ CTX_ARG ] . ty ;
1430
+ let old_resume_local = replace_local ( CTX_ARG , resume_ty, body, tcx) ;
1528
1431
1529
1432
// When first entering the coroutine, move the resume argument into its old local
1530
1433
// (which is now a generator interior).
1531
1434
let source_info = SourceInfo :: outermost ( body. span ) ;
1532
- let stmts = & mut body. basic_blocks_mut ( ) [ START_BLOCK ] . statements ;
1435
+ let stmts = & mut body. basic_blocks . as_mut ( ) [ START_BLOCK ] . statements ;
1436
+ let resume_rvalue = if matches ! (
1437
+ coroutine_kind,
1438
+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _)
1439
+ ) {
1440
+ body. local_decls [ CTX_ARG ] . ty = Ty :: new_task_context ( tcx) ;
1441
+ Rvalue :: WrapUnsafeBinder ( Operand :: Move ( CTX_ARG . into ( ) ) , resume_ty)
1442
+ } else {
1443
+ Rvalue :: Use ( Operand :: Move ( CTX_ARG . into ( ) ) )
1444
+ } ;
1533
1445
stmts. insert (
1534
1446
0 ,
1535
1447
Statement :: new (
1536
1448
source_info,
1537
- StatementKind :: Assign ( Box :: new ( (
1538
- old_resume_local. into ( ) ,
1539
- Rvalue :: Use ( Operand :: Move ( resume_local. into ( ) ) ) ,
1540
- ) ) ) ,
1449
+ StatementKind :: Assign ( Box :: new ( ( old_resume_local. into ( ) , resume_rvalue. clone ( ) ) ) ) ,
1541
1450
) ,
1542
1451
) ;
1543
1452
@@ -1580,6 +1489,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1580
1489
discr_ty,
1581
1490
old_ret_ty,
1582
1491
old_yield_ty,
1492
+ resume_rvalue,
1583
1493
} ;
1584
1494
transform. visit_body ( body) ;
1585
1495
0 commit comments