@@ -211,6 +211,9 @@ struct TransformVisitor<'tcx> {
211211    old_yield_ty :  Ty < ' tcx > , 
212212
213213    old_ret_ty :  Ty < ' tcx > , 
214+ 
215+     /// The rvalue that should be assigned to yield `resume_arg` place. 
216+ resume_rvalue :  Rvalue < ' tcx > , 
214217} 
215218
216219impl < ' tcx >  TransformVisitor < ' tcx >  { 
@@ -533,100 +536,6 @@ fn replace_local<'tcx>(
533536    new_local
534537} 
535538
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- 
630539/// Transforms the `body` of the coroutine applying the following transform: 
631540/// 
632541/// - Remove the `resume` argument. 
@@ -1342,12 +1251,11 @@ fn create_cases<'tcx>(
13421251
13431252                if  operation == Operation :: Resume  { 
13441253                    // Move the resume argument to the destination place of the `Yield` terminator 
1345-                     let  resume_arg = CTX_ARG ; 
13461254                    statements. push ( Statement :: new ( 
13471255                        source_info, 
13481256                        StatementKind :: Assign ( Box :: new ( ( 
13491257                            point. resume_arg , 
1350-                             Rvalue :: Use ( Operand :: Move ( resume_arg . into ( ) ) ) , 
1258+                             transform . resume_rvalue . clone ( ) , 
13511259                        ) ) ) , 
13521260                    ) ) ; 
13531261                } 
@@ -1504,12 +1412,8 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
15041412        )  && has_expandable_async_drops ( tcx,  body,  coroutine_ty) ; 
15051413
15061414        // 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) ; 
15131417
15141418            if  let  Some ( dumper)  = MirDumper :: new ( tcx,  "coroutine_async_drop_expand" ,  body)  { 
15151419                dumper. dump_mir ( body) ; 
@@ -1522,22 +1426,27 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
15221426        // This is needed because the resume argument `_2` might be live across a `yield`, in which 
15231427        // case there is no `Assign` to it that the transform can turn into a store to the coroutine 
15241428        // 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) ; 
15281431
15291432        // When first entering the coroutine, move the resume argument into its old local 
15301433        // (which is now a generator interior). 
15311434        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+         } ; 
15331445        stmts. insert ( 
15341446            0 , 
15351447            Statement :: new ( 
15361448                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 ( ) ) ) ) , 
15411450            ) , 
15421451        ) ; 
15431452
@@ -1580,6 +1489,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
15801489            discr_ty, 
15811490            old_ret_ty, 
15821491            old_yield_ty, 
1492+             resume_rvalue, 
15831493        } ; 
15841494        transform. visit_body ( body) ; 
15851495
0 commit comments