@@ -183,14 +183,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
183
183
self . arena . alloc_from_iter ( arms. iter ( ) . map ( |x| self . lower_arm ( x) ) ) ,
184
184
hir:: MatchSource :: Normal ,
185
185
) ,
186
- ExprKind :: Gen ( capture_clause, block, GenBlockKind :: Async ) => self . make_async_expr (
187
- * capture_clause,
188
- e. id ,
189
- None ,
190
- e. span ,
191
- hir:: CoroutineSource :: Block ,
192
- |this| this. with_new_scopes ( e. span , |this| this. lower_block_expr ( block) ) ,
193
- ) ,
194
186
ExprKind :: Await ( expr, await_kw_span) => self . lower_expr_await ( * await_kw_span, expr) ,
195
187
ExprKind :: Closure ( box Closure {
196
188
binder,
@@ -226,6 +218,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
226
218
* fn_arg_span,
227
219
) ,
228
220
} ,
221
+ ExprKind :: Gen ( capture_clause, block, coroutine_kind) => {
222
+ let coroutine_kind = match coroutine_kind {
223
+ GenBlockKind :: Async => hir:: CoroutineDesugaring :: Async ,
224
+ GenBlockKind :: Gen => hir:: CoroutineDesugaring :: Gen ,
225
+ GenBlockKind :: AsyncGen => hir:: CoroutineDesugaring :: AsyncGen ,
226
+ } ;
227
+ let coroutine_kind =
228
+ hir:: CoroutineKind :: Desugared ( coroutine_kind, hir:: CoroutineSource :: Block ) ;
229
+
230
+ self . make_desugared_coroutine_expr (
231
+ * capture_clause,
232
+ e. id ,
233
+ None ,
234
+ e. span ,
235
+ coroutine_kind,
236
+ |this| this. with_new_scopes ( e. span , |this| this. lower_block_expr ( block) ) ,
237
+ )
238
+ }
229
239
ExprKind :: Block ( blk, opt_label) => {
230
240
let opt_label = self . lower_label ( * opt_label) ;
231
241
hir:: ExprKind :: Block ( self . lower_block ( blk, opt_label. is_some ( ) ) , opt_label)
@@ -313,23 +323,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
313
323
rest,
314
324
)
315
325
}
316
- ExprKind :: Gen ( capture_clause, block, GenBlockKind :: Gen ) => self . make_gen_expr (
317
- * capture_clause,
318
- e. id ,
319
- None ,
320
- e. span ,
321
- hir:: CoroutineSource :: Block ,
322
- |this| this. with_new_scopes ( e. span , |this| this. lower_block_expr ( block) ) ,
323
- ) ,
324
- ExprKind :: Gen ( capture_clause, block, GenBlockKind :: AsyncGen ) => self
325
- . make_async_gen_expr (
326
- * capture_clause,
327
- e. id ,
328
- None ,
329
- e. span ,
330
- hir:: CoroutineSource :: Block ,
331
- |this| this. with_new_scopes ( e. span , |this| this. lower_block_expr ( block) ) ,
332
- ) ,
333
326
ExprKind :: Yield ( opt_expr) => self . lower_expr_yield ( e. span , opt_expr. as_deref ( ) ) ,
334
327
ExprKind :: Err => {
335
328
hir:: ExprKind :: Err ( self . dcx ( ) . span_delayed_bug ( e. span , "lowered ExprKind::Err" ) )
@@ -612,213 +605,94 @@ impl<'hir> LoweringContext<'_, 'hir> {
612
605
hir:: Arm { hir_id, pat, guard, body, span }
613
606
}
614
607
615
- /// Lower an `async` construct to a coroutine that implements `Future` .
608
+ /// Lower/desugar a coroutine construct .
616
609
///
617
- /// This results in:
618
- ///
619
- /// ```text
620
- /// static move? |_task_context| -> <ret_ty> {
621
- /// <body>
622
- /// }
623
- /// ```
624
- pub ( super ) fn make_async_expr (
625
- & mut self ,
626
- capture_clause : CaptureBy ,
627
- closure_node_id : NodeId ,
628
- ret_ty : Option < hir:: FnRetTy < ' hir > > ,
629
- span : Span ,
630
- async_coroutine_source : hir:: CoroutineSource ,
631
- body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
632
- ) -> hir:: ExprKind < ' hir > {
633
- let output = ret_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
634
-
635
- // Resume argument type: `ResumeTy`
636
- let unstable_span = self . mark_span_with_reason (
637
- DesugaringKind :: Async ,
638
- self . lower_span ( span) ,
639
- Some ( self . allow_gen_future . clone ( ) ) ,
640
- ) ;
641
- let resume_ty = self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span) ;
642
- let input_ty = hir:: Ty {
643
- hir_id : self . next_id ( ) ,
644
- kind : hir:: TyKind :: Path ( resume_ty) ,
645
- span : unstable_span,
646
- } ;
647
-
648
- // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
649
- let fn_decl = self . arena . alloc ( hir:: FnDecl {
650
- inputs : arena_vec ! [ self ; input_ty] ,
651
- output,
652
- c_variadic : false ,
653
- implicit_self : hir:: ImplicitSelfKind :: None ,
654
- lifetime_elision_allowed : false ,
655
- } ) ;
656
-
657
- // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
658
- let ( pat, task_context_hid) = self . pat_ident_binding_mode (
659
- span,
660
- Ident :: with_dummy_span ( sym:: _task_context) ,
661
- hir:: BindingAnnotation :: MUT ,
662
- ) ;
663
- let param = hir:: Param {
664
- hir_id : self . next_id ( ) ,
665
- pat,
666
- ty_span : self . lower_span ( span) ,
667
- span : self . lower_span ( span) ,
668
- } ;
669
- let params = arena_vec ! [ self ; param] ;
670
-
671
- let coroutine_kind =
672
- hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , async_coroutine_source) ;
673
- let body = self . lower_body ( move |this| {
674
- this. coroutine_kind = Some ( coroutine_kind) ;
675
-
676
- let old_ctx = this. task_context ;
677
- this. task_context = Some ( task_context_hid) ;
678
- let res = body ( this) ;
679
- this. task_context = old_ctx;
680
- ( params, res)
681
- } ) ;
682
-
683
- // `static |_task_context| -> <ret_ty> { body }`:
684
- hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
685
- def_id : self . local_def_id ( closure_node_id) ,
686
- binder : hir:: ClosureBinder :: Default ,
687
- capture_clause,
688
- bound_generic_params : & [ ] ,
689
- fn_decl,
690
- body,
691
- fn_decl_span : self . lower_span ( span) ,
692
- fn_arg_span : None ,
693
- kind : hir:: ClosureKind :: Coroutine ( coroutine_kind) ,
694
- constness : hir:: Constness :: NotConst ,
695
- } ) )
696
- }
697
-
698
- /// Lower a `gen` construct to a generator that implements `Iterator`.
610
+ /// In particular, this creates the correct async resume argument and `_task_context`.
699
611
///
700
612
/// This results in:
701
613
///
702
614
/// ```text
703
- /// static move? |() | -> () {
615
+ /// static move? |<_task_context?> | -> <return_ty> {
704
616
/// <body>
705
617
/// }
706
618
/// ```
707
- pub ( super ) fn make_gen_expr (
619
+ pub ( super ) fn make_desugared_coroutine_expr (
708
620
& mut self ,
709
621
capture_clause : CaptureBy ,
710
622
closure_node_id : NodeId ,
711
- _yield_ty : Option < hir:: FnRetTy < ' hir > > ,
623
+ return_ty : Option < hir:: FnRetTy < ' hir > > ,
712
624
span : Span ,
713
- coroutine_source : hir:: CoroutineSource ,
625
+ coroutine_kind : hir:: CoroutineKind ,
714
626
body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
715
627
) -> hir:: ExprKind < ' hir > {
716
- let output = hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ;
717
-
718
- // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
719
- let fn_decl = self . arena . alloc ( hir:: FnDecl {
720
- inputs : & [ ] ,
721
- output,
722
- c_variadic : false ,
723
- implicit_self : hir:: ImplicitSelfKind :: None ,
724
- lifetime_elision_allowed : false ,
725
- } ) ;
726
-
727
- let coroutine_kind =
728
- hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Gen , coroutine_source) ;
729
- let body = self . lower_body ( move |this| {
730
- this. coroutine_kind = Some ( coroutine_kind) ;
731
-
732
- let res = body ( this) ;
733
- ( & [ ] , res)
734
- } ) ;
628
+ let is_async = match coroutine_kind {
629
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _) => true ,
630
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: AsyncGen , _) => true ,
631
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Gen , _) => false ,
632
+ _ => panic ! ( "expected a `CoroutineKind::Desugared`" ) ,
633
+ } ;
735
634
736
- // `static |()| -> () { body }`:
737
- hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
738
- def_id : self . local_def_id ( closure_node_id) ,
739
- binder : hir:: ClosureBinder :: Default ,
740
- capture_clause,
741
- bound_generic_params : & [ ] ,
742
- fn_decl,
743
- body,
744
- fn_decl_span : self . lower_span ( span) ,
745
- fn_arg_span : None ,
746
- kind : hir:: ClosureKind :: Coroutine ( coroutine_kind) ,
747
- constness : hir:: Constness :: NotConst ,
748
- } ) )
749
- }
635
+ // The `async` desugaring takes a resume argument and maintains a `task_context`,
636
+ // whereas a generator does not.
637
+ let ( inputs, params, task_context) : ( & [ _ ] , & [ _ ] , _ ) = if is_async {
638
+ // Resume argument type: `ResumeTy`
639
+ let unstable_span = self . mark_span_with_reason (
640
+ DesugaringKind :: Async ,
641
+ self . lower_span ( span) ,
642
+ Some ( self . allow_gen_future . clone ( ) ) ,
643
+ ) ;
644
+ let resume_ty = self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span) ;
645
+ let input_ty = hir:: Ty {
646
+ hir_id : self . next_id ( ) ,
647
+ kind : hir:: TyKind :: Path ( resume_ty) ,
648
+ span : unstable_span,
649
+ } ;
650
+ let inputs = arena_vec ! [ self ; input_ty] ;
750
651
751
- /// Lower a `async gen` construct to a generator that implements `AsyncIterator`.
752
- ///
753
- /// This results in:
754
- ///
755
- /// ```text
756
- /// static move? |_task_context| -> () {
757
- /// <body>
758
- /// }
759
- /// ```
760
- pub ( super ) fn make_async_gen_expr (
761
- & mut self ,
762
- capture_clause : CaptureBy ,
763
- closure_node_id : NodeId ,
764
- _yield_ty : Option < hir:: FnRetTy < ' hir > > ,
765
- span : Span ,
766
- async_coroutine_source : hir:: CoroutineSource ,
767
- body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
768
- ) -> hir:: ExprKind < ' hir > {
769
- let output = hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ;
652
+ // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
653
+ let ( pat, task_context_hid) = self . pat_ident_binding_mode (
654
+ span,
655
+ Ident :: with_dummy_span ( sym:: _task_context) ,
656
+ hir:: BindingAnnotation :: MUT ,
657
+ ) ;
658
+ let param = hir:: Param {
659
+ hir_id : self . next_id ( ) ,
660
+ pat,
661
+ ty_span : self . lower_span ( span) ,
662
+ span : self . lower_span ( span) ,
663
+ } ;
664
+ let params = arena_vec ! [ self ; param] ;
770
665
771
- // Resume argument type: `ResumeTy`
772
- let unstable_span = self . mark_span_with_reason (
773
- DesugaringKind :: Async ,
774
- self . lower_span ( span) ,
775
- Some ( self . allow_gen_future . clone ( ) ) ,
776
- ) ;
777
- let resume_ty = self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span) ;
778
- let input_ty = hir:: Ty {
779
- hir_id : self . next_id ( ) ,
780
- kind : hir:: TyKind :: Path ( resume_ty) ,
781
- span : unstable_span,
666
+ ( inputs, params, Some ( task_context_hid) )
667
+ } else {
668
+ ( & [ ] , & [ ] , None )
782
669
} ;
783
670
784
- // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
671
+ let output =
672
+ return_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
673
+
785
674
let fn_decl = self . arena . alloc ( hir:: FnDecl {
786
- inputs : arena_vec ! [ self ; input_ty ] ,
675
+ inputs,
787
676
output,
788
677
c_variadic : false ,
789
678
implicit_self : hir:: ImplicitSelfKind :: None ,
790
679
lifetime_elision_allowed : false ,
791
680
} ) ;
792
681
793
- // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
794
- let ( pat, task_context_hid) = self . pat_ident_binding_mode (
795
- span,
796
- Ident :: with_dummy_span ( sym:: _task_context) ,
797
- hir:: BindingAnnotation :: MUT ,
798
- ) ;
799
- let param = hir:: Param {
800
- hir_id : self . next_id ( ) ,
801
- pat,
802
- ty_span : self . lower_span ( span) ,
803
- span : self . lower_span ( span) ,
804
- } ;
805
- let params = arena_vec ! [ self ; param] ;
806
-
807
- let coroutine_kind = hir:: CoroutineKind :: Desugared (
808
- hir:: CoroutineDesugaring :: AsyncGen ,
809
- async_coroutine_source,
810
- ) ;
811
682
let body = self . lower_body ( move |this| {
812
683
this. coroutine_kind = Some ( coroutine_kind) ;
813
684
814
685
let old_ctx = this. task_context ;
815
- this. task_context = Some ( task_context_hid) ;
686
+ if task_context. is_some ( ) {
687
+ this. task_context = task_context;
688
+ }
816
689
let res = body ( this) ;
817
690
this. task_context = old_ctx;
691
+
818
692
( params, res)
819
693
} ) ;
820
694
821
- // `static |_task_context| -> <ret_ty > { body }`:
695
+ // `static |< _task_context?> | -> <return_ty > { < body> }`:
822
696
hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
823
697
def_id : self . local_def_id ( closure_node_id) ,
824
698
binder : hir:: ClosureBinder :: Default ,
@@ -1203,12 +1077,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
1203
1077
None
1204
1078
} ;
1205
1079
1206
- let async_body = this. make_async_expr (
1080
+ let async_body = this. make_desugared_coroutine_expr (
1207
1081
capture_clause,
1208
1082
inner_closure_id,
1209
1083
async_ret_ty,
1210
1084
body. span ,
1211
- hir:: CoroutineSource :: Closure ,
1085
+ hir:: CoroutineKind :: Desugared (
1086
+ hir:: CoroutineDesugaring :: Async ,
1087
+ hir:: CoroutineSource :: Closure ,
1088
+ ) ,
1212
1089
|this| this. with_new_scopes ( fn_decl_span, |this| this. lower_expr_mut ( body) ) ,
1213
1090
) ;
1214
1091
let hir_id = this. lower_node_id ( inner_closure_id) ;
0 commit comments