@@ -132,8 +132,8 @@ struct SelfArgVisitor<'tcx> {
132132}
133133
134134impl < ' tcx > SelfArgVisitor < ' tcx > {
135- fn new ( tcx : TyCtxt < ' tcx > , elem : ProjectionElem < Local , Ty < ' tcx > > ) -> Self {
136- Self { tcx, new_base : Place { local : SELF_ARG , projection : tcx . mk_place_elems ( & [ elem ] ) } }
135+ fn new ( tcx : TyCtxt < ' tcx > , new_base : Place < ' tcx > ) -> Self {
136+ Self { tcx, new_base }
137137 }
138138}
139139
@@ -146,16 +146,14 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
146146 assert_ne ! ( * local, SELF_ARG ) ;
147147 }
148148
149- fn visit_place ( & mut self , place : & mut Place < ' tcx > , context : PlaceContext , location : Location ) {
149+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , _ : PlaceContext , _ : Location ) {
150150 if place. local == SELF_ARG {
151151 replace_base ( place, self . new_base , self . tcx ) ;
152- } else {
153- self . visit_local ( & mut place. local , context, location) ;
152+ }
154153
155- for elem in place. projection . iter ( ) {
156- if let PlaceElem :: Index ( local) = elem {
157- assert_ne ! ( local, SELF_ARG ) ;
158- }
154+ for elem in place. projection . iter ( ) {
155+ if let PlaceElem :: Index ( local) = elem {
156+ assert_ne ! ( local, SELF_ARG ) ;
159157 }
160158 }
161159 }
@@ -520,32 +518,49 @@ fn make_aggregate_adt<'tcx>(
520518
521519#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
522520fn make_coroutine_state_argument_indirect < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
523- let coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
521+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
524522
525523 let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
526524
527525 // Replace the by value coroutine argument
528- body. local_decls . raw [ 1 ] . ty = ref_coroutine_ty;
526+ body. local_decls [ SELF_ARG ] . ty = ref_coroutine_ty;
529527
530528 // Add a deref to accesses of the coroutine state
531- SelfArgVisitor :: new ( tcx, ProjectionElem :: Deref ) . visit_body ( body) ;
529+ SelfArgVisitor :: new ( tcx, tcx . mk_place_deref ( SELF_ARG . into ( ) ) ) . visit_body ( body) ;
532530}
533531
534532#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
535533fn make_coroutine_state_argument_pinned < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
536- let ref_coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
534+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
535+
536+ let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
537537
538538 let pin_did = tcx. require_lang_item ( LangItem :: Pin , body. span ) ;
539539 let pin_adt_ref = tcx. adt_def ( pin_did) ;
540540 let args = tcx. mk_args ( & [ ref_coroutine_ty. into ( ) ] ) ;
541541 let pin_ref_coroutine_ty = Ty :: new_adt ( tcx, pin_adt_ref, args) ;
542542
543543 // Replace the by ref coroutine argument
544- body. local_decls . raw [ 1 ] . ty = pin_ref_coroutine_ty;
544+ body. local_decls [ SELF_ARG ] . ty = pin_ref_coroutine_ty;
545+
546+ let unpinned_local = body. local_decls . push ( LocalDecl :: new ( ref_coroutine_ty, body. span ) ) ;
545547
546548 // Add the Pin field access to accesses of the coroutine state
547- SelfArgVisitor :: new ( tcx, ProjectionElem :: Field ( FieldIdx :: ZERO , ref_coroutine_ty) )
548- . visit_body ( body) ;
549+ SelfArgVisitor :: new ( tcx, tcx. mk_place_deref ( unpinned_local. into ( ) ) ) . visit_body ( body) ;
550+
551+ let source_info = SourceInfo :: outermost ( body. span ) ;
552+ let pin_field = tcx. mk_place_field ( SELF_ARG . into ( ) , FieldIdx :: ZERO , ref_coroutine_ty) ;
553+
554+ body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
555+ 0 ,
556+ Statement :: new (
557+ source_info,
558+ StatementKind :: Assign ( Box :: new ( (
559+ unpinned_local. into ( ) ,
560+ Rvalue :: Use ( Operand :: Copy ( pin_field) ) ,
561+ ) ) ) ,
562+ ) ,
563+ ) ;
549564}
550565
551566/// Transforms the `body` of the coroutine applying the following transforms:
@@ -1297,8 +1312,6 @@ fn create_coroutine_resume_function<'tcx>(
12971312 let default_block = insert_term_block ( body, TerminatorKind :: Unreachable ) ;
12981313 insert_switch ( body, cases, & transform, default_block) ;
12991314
1300- make_coroutine_state_argument_indirect ( tcx, body) ;
1301-
13021315 match transform. coroutine_kind {
13031316 CoroutineKind :: Coroutine ( _)
13041317 | CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _) =>
@@ -1307,7 +1320,9 @@ fn create_coroutine_resume_function<'tcx>(
13071320 }
13081321 // Iterator::next doesn't accept a pinned argument,
13091322 // unlike for all other coroutine kinds.
1310- CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => { }
1323+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => {
1324+ make_coroutine_state_argument_indirect ( tcx, body) ;
1325+ }
13111326 }
13121327
13131328 // Make sure we remove dead blocks to remove
0 commit comments