@@ -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,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
226
218
* fn_arg_span,
227
219
) ,
228
220
} ,
221
+ ExprKind :: Gen ( capture_clause, block, genblock_kind) => {
222
+ let desugaring_kind = match genblock_kind {
223
+ GenBlockKind :: Async => hir:: CoroutineDesugaring :: Async ,
224
+ GenBlockKind :: Gen => hir:: CoroutineDesugaring :: Gen ,
225
+ GenBlockKind :: AsyncGen => hir:: CoroutineDesugaring :: AsyncGen ,
226
+ } ;
227
+ self . make_desugared_coroutine_expr (
228
+ * capture_clause,
229
+ e. id ,
230
+ None ,
231
+ e. span ,
232
+ desugaring_kind,
233
+ hir:: CoroutineSource :: Block ,
234
+ |this| this. with_new_scopes ( e. span , |this| this. lower_block_expr ( block) ) ,
235
+ )
236
+ }
229
237
ExprKind :: Block ( blk, opt_label) => {
230
238
let opt_label = self . lower_label ( * opt_label) ;
231
239
hir:: ExprKind :: Block ( self . lower_block ( blk, opt_label. is_some ( ) ) , opt_label)
@@ -313,23 +321,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
313
321
rest,
314
322
)
315
323
}
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
324
ExprKind :: Yield ( opt_expr) => self . lower_expr_yield ( e. span , opt_expr. as_deref ( ) ) ,
334
325
ExprKind :: Err => {
335
326
hir:: ExprKind :: Err ( self . dcx ( ) . span_delayed_bug ( e. span , "lowered ExprKind::Err" ) )
@@ -612,213 +603,94 @@ impl<'hir> LoweringContext<'_, 'hir> {
612
603
hir:: Arm { hir_id, pat, guard, body, span }
613
604
}
614
605
615
- /// Lower an `async` construct to a coroutine that implements `Future`.
616
- ///
617
- /// This results in:
606
+ /// Lower/desugar a coroutine construct.
618
607
///
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`.
608
+ /// In particular, this creates the correct async resume argument and `_task_context`.
699
609
///
700
610
/// This results in:
701
611
///
702
612
/// ```text
703
- /// static move? |() | -> () {
613
+ /// static move? |<_task_context?> | -> <return_ty> {
704
614
/// <body>
705
615
/// }
706
616
/// ```
707
- pub ( super ) fn make_gen_expr (
617
+ pub ( super ) fn make_desugared_coroutine_expr (
708
618
& mut self ,
709
619
capture_clause : CaptureBy ,
710
620
closure_node_id : NodeId ,
711
- _yield_ty : Option < hir:: FnRetTy < ' hir > > ,
621
+ return_ty : Option < hir:: FnRetTy < ' hir > > ,
712
622
span : Span ,
623
+ desugaring_kind : hir:: CoroutineDesugaring ,
713
624
coroutine_source : hir:: CoroutineSource ,
714
625
body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
715
626
) -> 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
- } ) ;
735
-
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
- }
627
+ let coroutine_kind = hir:: CoroutineKind :: Desugared ( desugaring_kind, coroutine_source) ;
628
+
629
+ // The `async` desugaring takes a resume argument and maintains a `task_context`,
630
+ // whereas a generator does not.
631
+ let ( inputs, params, task_context) : ( & [ _ ] , & [ _ ] , _ ) = if match desugaring_kind {
632
+ hir:: CoroutineDesugaring :: Async => true ,
633
+ hir:: CoroutineDesugaring :: Gen => false ,
634
+ hir:: CoroutineDesugaring :: AsyncGen => true ,
635
+ } {
636
+ // Resume argument type: `ResumeTy`
637
+ let unstable_span = self . mark_span_with_reason (
638
+ DesugaringKind :: Async ,
639
+ self . lower_span ( span) ,
640
+ Some ( self . allow_gen_future . clone ( ) ) ,
641
+ ) ;
642
+ let resume_ty = self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span) ;
643
+ let input_ty = hir:: Ty {
644
+ hir_id : self . next_id ( ) ,
645
+ kind : hir:: TyKind :: Path ( resume_ty) ,
646
+ span : unstable_span,
647
+ } ;
648
+ let inputs = arena_vec ! [ self ; input_ty] ;
750
649
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) ) ;
650
+ // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
651
+ let ( pat, task_context_hid) = self . pat_ident_binding_mode (
652
+ span,
653
+ Ident :: with_dummy_span ( sym:: _task_context) ,
654
+ hir:: BindingAnnotation :: MUT ,
655
+ ) ;
656
+ let param = hir:: Param {
657
+ hir_id : self . next_id ( ) ,
658
+ pat,
659
+ ty_span : self . lower_span ( span) ,
660
+ span : self . lower_span ( span) ,
661
+ } ;
662
+ let params = arena_vec ! [ self ; param] ;
770
663
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,
664
+ ( inputs, params, Some ( task_context_hid) )
665
+ } else {
666
+ ( & [ ] , & [ ] , None )
782
667
} ;
783
668
784
- // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
669
+ let output =
670
+ return_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
671
+
785
672
let fn_decl = self . arena . alloc ( hir:: FnDecl {
786
- inputs : arena_vec ! [ self ; input_ty ] ,
673
+ inputs,
787
674
output,
788
675
c_variadic : false ,
789
676
implicit_self : hir:: ImplicitSelfKind :: None ,
790
677
lifetime_elision_allowed : false ,
791
678
} ) ;
792
679
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
680
let body = self . lower_body ( move |this| {
812
681
this. coroutine_kind = Some ( coroutine_kind) ;
813
682
814
683
let old_ctx = this. task_context ;
815
- this. task_context = Some ( task_context_hid) ;
684
+ if task_context. is_some ( ) {
685
+ this. task_context = task_context;
686
+ }
816
687
let res = body ( this) ;
817
688
this. task_context = old_ctx;
689
+
818
690
( params, res)
819
691
} ) ;
820
692
821
- // `static |_task_context| -> <ret_ty > { body }`:
693
+ // `static |< _task_context?> | -> <return_ty > { < body> }`:
822
694
hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
823
695
def_id : self . local_def_id ( closure_node_id) ,
824
696
binder : hir:: ClosureBinder :: Default ,
@@ -1203,11 +1075,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
1203
1075
None
1204
1076
} ;
1205
1077
1206
- let async_body = this. make_async_expr (
1078
+ let async_body = this. make_desugared_coroutine_expr (
1207
1079
capture_clause,
1208
1080
inner_closure_id,
1209
1081
async_ret_ty,
1210
1082
body. span ,
1083
+ hir:: CoroutineDesugaring :: Async ,
1211
1084
hir:: CoroutineSource :: Closure ,
1212
1085
|this| this. with_new_scopes ( fn_decl_span, |this| this. lower_expr_mut ( body) ) ,
1213
1086
) ;
0 commit comments