@@ -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 }
@@ -515,32 +513,51 @@ fn make_aggregate_adt<'tcx>(
515513
516514#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
517515fn make_coroutine_state_argument_indirect < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
518- let coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
516+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
519517
520518 let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
521519
522520 // Replace the by value coroutine argument
523- body. local_decls . raw [ 1 ] . ty = ref_coroutine_ty;
521+ body. local_decls [ SELF_ARG ] . ty = ref_coroutine_ty;
524522
525523 // Add a deref to accesses of the coroutine state
526- SelfArgVisitor :: new ( tcx, ProjectionElem :: Deref ) . visit_body ( body) ;
524+ SelfArgVisitor :: new ( tcx, tcx . mk_place_deref ( SELF_ARG . into ( ) ) ) . visit_body ( body) ;
527525}
528526
529527#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
530528fn make_coroutine_state_argument_pinned < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
531- let ref_coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
529+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
530+
531+ let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
532532
533533 let pin_did = tcx. require_lang_item ( LangItem :: Pin , body. span ) ;
534534 let pin_adt_ref = tcx. adt_def ( pin_did) ;
535535 let args = tcx. mk_args ( & [ ref_coroutine_ty. into ( ) ] ) ;
536536 let pin_ref_coroutine_ty = Ty :: new_adt ( tcx, pin_adt_ref, args) ;
537537
538538 // Replace the by ref coroutine argument
539- body. local_decls . raw [ 1 ] . ty = pin_ref_coroutine_ty;
539+ body. local_decls [ SELF_ARG ] . ty = pin_ref_coroutine_ty;
540+
541+ let unpinned_local = body. local_decls . push ( LocalDecl :: new ( ref_coroutine_ty, body. span ) ) ;
540542
541543 // Add the Pin field access to accesses of the coroutine state
542- SelfArgVisitor :: new ( tcx, ProjectionElem :: Field ( FieldIdx :: ZERO , ref_coroutine_ty) )
543- . visit_body ( body) ;
544+ SelfArgVisitor :: new ( tcx, tcx. mk_place_deref ( unpinned_local. into ( ) ) ) . visit_body ( body) ;
545+
546+ let source_info = SourceInfo :: outermost ( body. span ) ;
547+ body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
548+ 0 ,
549+ Statement :: new (
550+ source_info,
551+ StatementKind :: Assign ( Box :: new ( (
552+ unpinned_local. into ( ) ,
553+ Rvalue :: CopyForDeref ( tcx. mk_place_field (
554+ SELF_ARG . into ( ) ,
555+ FieldIdx :: ZERO ,
556+ ref_coroutine_ty,
557+ ) ) ,
558+ ) ) ) ,
559+ ) ,
560+ ) ;
544561}
545562
546563/// Transforms the `body` of the coroutine applying the following transforms:
@@ -1292,8 +1309,6 @@ fn create_coroutine_resume_function<'tcx>(
12921309 let default_block = insert_term_block ( body, TerminatorKind :: Unreachable ) ;
12931310 insert_switch ( body, cases, & transform, default_block) ;
12941311
1295- make_coroutine_state_argument_indirect ( tcx, body) ;
1296-
12971312 match transform. coroutine_kind {
12981313 CoroutineKind :: Coroutine ( _)
12991314 | CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _) =>
@@ -1302,7 +1317,9 @@ fn create_coroutine_resume_function<'tcx>(
13021317 }
13031318 // Iterator::next doesn't accept a pinned argument,
13041319 // unlike for all other coroutine kinds.
1305- CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => { }
1320+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => {
1321+ make_coroutine_state_argument_indirect ( tcx, body) ;
1322+ }
13061323 }
13071324}
13081325
0 commit comments