@@ -133,8 +133,8 @@ struct SelfArgVisitor<'tcx> {
133133}
134134
135135impl < ' tcx > SelfArgVisitor < ' tcx > {
136- fn new ( tcx : TyCtxt < ' tcx > , elem : ProjectionElem < Local , Ty < ' tcx > > ) -> Self {
137- Self { tcx, new_base : Place { local : SELF_ARG , projection : tcx . mk_place_elems ( & [ elem ] ) } }
136+ fn new ( tcx : TyCtxt < ' tcx > , new_base : Place < ' tcx > ) -> Self {
137+ Self { tcx, new_base }
138138 }
139139}
140140
@@ -147,16 +147,14 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
147147 assert_ne ! ( * local, SELF_ARG ) ;
148148 }
149149
150- fn visit_place ( & mut self , place : & mut Place < ' tcx > , context : PlaceContext , location : Location ) {
150+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , _ : PlaceContext , _ : Location ) {
151151 if place. local == SELF_ARG {
152152 replace_base ( place, self . new_base , self . tcx ) ;
153- } else {
154- self . visit_local ( & mut place. local , context, location) ;
153+ }
155154
156- for elem in place. projection . iter ( ) {
157- if let PlaceElem :: Index ( local) = elem {
158- assert_ne ! ( local, SELF_ARG ) ;
159- }
155+ for elem in place. projection . iter ( ) {
156+ if let PlaceElem :: Index ( local) = elem {
157+ assert_ne ! ( local, SELF_ARG ) ;
160158 }
161159 }
162160 }
@@ -516,32 +514,51 @@ fn make_aggregate_adt<'tcx>(
516514
517515#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
518516fn make_coroutine_state_argument_indirect < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
519- let coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
517+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
520518
521519 let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
522520
523521 // Replace the by value coroutine argument
524- body. local_decls . raw [ 1 ] . ty = ref_coroutine_ty;
522+ body. local_decls [ SELF_ARG ] . ty = ref_coroutine_ty;
525523
526524 // Add a deref to accesses of the coroutine state
527- SelfArgVisitor :: new ( tcx, ProjectionElem :: Deref ) . visit_body ( body) ;
525+ SelfArgVisitor :: new ( tcx, tcx . mk_place_deref ( SELF_ARG . into ( ) ) ) . visit_body ( body) ;
528526}
529527
530528#[ tracing:: instrument( level = "trace" , skip( tcx, body) ) ]
531529fn make_coroutine_state_argument_pinned < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
532- let ref_coroutine_ty = body. local_decls . raw [ 1 ] . ty ;
530+ let coroutine_ty = body. local_decls [ SELF_ARG ] . ty ;
531+
532+ let ref_coroutine_ty = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_ty) ;
533533
534534 let pin_did = tcx. require_lang_item ( LangItem :: Pin , body. span ) ;
535535 let pin_adt_ref = tcx. adt_def ( pin_did) ;
536536 let args = tcx. mk_args ( & [ ref_coroutine_ty. into ( ) ] ) ;
537537 let pin_ref_coroutine_ty = Ty :: new_adt ( tcx, pin_adt_ref, args) ;
538538
539539 // Replace the by ref coroutine argument
540- body. local_decls . raw [ 1 ] . ty = pin_ref_coroutine_ty;
540+ body. local_decls [ SELF_ARG ] . ty = pin_ref_coroutine_ty;
541+
542+ let unpinned_local = body. local_decls . push ( LocalDecl :: new ( ref_coroutine_ty, body. span ) ) ;
541543
542544 // Add the Pin field access to accesses of the coroutine state
543- SelfArgVisitor :: new ( tcx, ProjectionElem :: Field ( FieldIdx :: ZERO , ref_coroutine_ty) )
544- . visit_body ( body) ;
545+ SelfArgVisitor :: new ( tcx, tcx. mk_place_deref ( unpinned_local. into ( ) ) ) . visit_body ( body) ;
546+
547+ let source_info = SourceInfo :: outermost ( body. span ) ;
548+ body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
549+ 0 ,
550+ Statement :: new (
551+ source_info,
552+ StatementKind :: Assign ( Box :: new ( (
553+ unpinned_local. into ( ) ,
554+ Rvalue :: CopyForDeref ( tcx. mk_place_field (
555+ SELF_ARG . into ( ) ,
556+ FieldIdx :: ZERO ,
557+ ref_coroutine_ty,
558+ ) ) ,
559+ ) ) ) ,
560+ ) ,
561+ ) ;
545562}
546563
547564/// Transforms the `body` of the coroutine applying the following transforms:
@@ -1293,8 +1310,6 @@ fn create_coroutine_resume_function<'tcx>(
12931310 let default_block = insert_term_block ( body, TerminatorKind :: Unreachable ) ;
12941311 insert_switch ( body, cases, & transform, default_block) ;
12951312
1296- make_coroutine_state_argument_indirect ( tcx, body) ;
1297-
12981313 match transform. coroutine_kind {
12991314 CoroutineKind :: Coroutine ( _)
13001315 | CoroutineKind :: Desugared ( CoroutineDesugaring :: Async | CoroutineDesugaring :: AsyncGen , _) =>
@@ -1303,7 +1318,9 @@ fn create_coroutine_resume_function<'tcx>(
13031318 }
13041319 // Iterator::next doesn't accept a pinned argument,
13051320 // unlike for all other coroutine kinds.
1306- CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => { }
1321+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Gen , _) => {
1322+ make_coroutine_state_argument_indirect ( tcx, body) ;
1323+ }
13071324 }
13081325}
13091326
0 commit comments