@@ -130,8 +130,8 @@ struct SelfArgVisitor<'tcx> {
130130}
131131
132132impl < ' tcx > SelfArgVisitor < ' tcx > {
133- fn new ( tcx : TyCtxt < ' tcx > , elem : ProjectionElem < Local , Ty < ' tcx > > ) -> Self {
134- Self { tcx, new_base : Place { local : SELF_ARG , projection : tcx . mk_place_elems ( & [ elem ] ) } }
133+ fn new ( tcx : TyCtxt < ' tcx > , new_base : Place < ' tcx > ) -> Self {
134+ Self { tcx, new_base }
135135 }
136136}
137137
@@ -144,16 +144,14 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
144144 assert_ne ! ( * local, SELF_ARG ) ;
145145 }
146146
147- fn visit_place ( & mut self , place : & mut Place < ' tcx > , context : PlaceContext , location : Location ) {
147+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , _ : PlaceContext , _ : Location ) {
148148 if place. local == SELF_ARG {
149149 replace_base ( place, self . new_base , self . tcx ) ;
150- } else {
151- self . visit_local ( & mut place. local , context, location) ;
150+ }
152151
153- for elem in place. projection . iter ( ) {
154- if let PlaceElem :: Index ( local) = elem {
155- assert_ne ! ( local, SELF_ARG ) ;
156- }
152+ for elem in place. projection . iter ( ) {
153+ if let PlaceElem :: Index ( local) = elem {
154+ assert_ne ! ( local, SELF_ARG ) ;
157155 }
158156 }
159157 }
@@ -484,31 +482,50 @@ fn make_aggregate_adt<'tcx>(
484482}
485483
486484fn make_coroutine_state_argument_indirect < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
487- let coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
485+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
488486
489487 let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
490488
491489 // Replace the by value coroutine argument
492- body. local_decls . raw [ 1 ] . ty = ref_coroutine_ty;
490+ body. local_decls [ SELF_ARG ] . ty = ref_coroutine_ty;
493491
494492 // Add a deref to accesses of the coroutine state
495- SelfArgVisitor :: new ( tcx, ProjectionElem :: Deref ) . visit_body ( body) ;
493+ SelfArgVisitor :: new ( tcx, tcx . mk_place_deref ( SELF_ARG . into ( ) ) ) . visit_body ( body) ;
496494}
497495
498496fn make_coroutine_state_argument_pinned < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
499- let ref_coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
497+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
498+
499+ let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
500500
501501 let pin_did = tcx. require_lang_item ( LangItem :: Pin , body. span ) ;
502502 let pin_adt_ref = tcx. adt_def ( pin_did) ;
503503 let args = tcx. mk_args ( & [ ref_coroutine_ty. into ( ) ] ) ;
504504 let pin_ref_coroutine_ty = Ty :: new_adt ( tcx, pin_adt_ref, args) ;
505505
506506 // Replace the by ref coroutine argument
507- body. local_decls . raw [ 1 ] . ty = pin_ref_coroutine_ty;
507+ body. local_decls [ SELF_ARG ] . ty = pin_ref_coroutine_ty;
508+
509+ let unpinned_local = body. local_decls . push ( LocalDecl :: new ( ref_coroutine_ty, body. span ) ) ;
508510
509511 // Add the Pin field access to accesses of the coroutine state
510- SelfArgVisitor :: new ( tcx, ProjectionElem :: Field ( FieldIdx :: ZERO , ref_coroutine_ty) )
511- . visit_body ( body) ;
512+ SelfArgVisitor :: new ( tcx, tcx. mk_place_deref ( unpinned_local. into ( ) ) ) . visit_body ( body) ;
513+
514+ let source_info = SourceInfo :: outermost ( body. span ) ;
515+ body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
516+ 0 ,
517+ Statement :: new (
518+ source_info,
519+ StatementKind :: Assign ( Box :: new ( (
520+ unpinned_local. into ( ) ,
521+ Rvalue :: CopyForDeref ( tcx. mk_place_field (
522+ SELF_ARG . into ( ) ,
523+ FieldIdx :: ZERO ,
524+ ref_coroutine_ty,
525+ ) ) ,
526+ ) ) ) ,
527+ ) ,
528+ ) ;
512529}
513530
514531/// Allocates a new local and replaces all references of `local` with it. Returns the new local.
@@ -1274,8 +1291,6 @@ fn create_coroutine_resume_function<'tcx>(
12741291 let default_block = insert_term_block ( body, TerminatorKind :: Unreachable ) ;
12751292 insert_switch ( body, cases, & transform, default_block) ;
12761293
1277- make_coroutine_state_argument_indirect ( tcx, body) ;
1278-
12791294 match transform. coroutine_kind {
12801295 CoroutineKind :: Coroutine ( _)
12811296 | CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _) =>
@@ -1284,7 +1299,9 @@ fn create_coroutine_resume_function<'tcx>(
12841299 }
12851300 // Iterator::next doesn't accept a pinned argument,
12861301 // unlike for all other coroutine kinds.
1287- CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => { }
1302+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => {
1303+ make_coroutine_state_argument_indirect ( tcx, body) ;
1304+ }
12881305 }
12891306
12901307 // Make sure we remove dead blocks to remove
0 commit comments