@@ -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,91 @@ 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` .
606
+ /// Lower/desugar a coroutine construct .
616
607
///
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`.
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) : ( & [ _ ] , & [ _ ] , _ ) = match desugaring_kind {
632
+ hir:: CoroutineDesugaring :: Async | hir:: CoroutineDesugaring :: AsyncGen => {
633
+ // Resume argument type: `ResumeTy`
634
+ let unstable_span = self . mark_span_with_reason (
635
+ DesugaringKind :: Async ,
636
+ self . lower_span ( span) ,
637
+ Some ( self . allow_gen_future . clone ( ) ) ,
638
+ ) ;
639
+ let resume_ty = self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span) ;
640
+ let input_ty = hir:: Ty {
641
+ hir_id : self . next_id ( ) ,
642
+ kind : hir:: TyKind :: Path ( resume_ty) ,
643
+ span : unstable_span,
644
+ } ;
645
+ let inputs = arena_vec ! [ self ; input_ty] ;
750
646
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) ) ;
647
+ // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
648
+ let ( pat, task_context_hid) = self . pat_ident_binding_mode (
649
+ span,
650
+ Ident :: with_dummy_span ( sym:: _task_context) ,
651
+ hir:: BindingAnnotation :: MUT ,
652
+ ) ;
653
+ let param = hir:: Param {
654
+ hir_id : self . next_id ( ) ,
655
+ pat,
656
+ ty_span : self . lower_span ( span) ,
657
+ span : self . lower_span ( span) ,
658
+ } ;
659
+ let params = arena_vec ! [ self ; param] ;
770
660
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,
661
+ ( inputs, params, Some ( task_context_hid) )
662
+ }
663
+ hir:: CoroutineDesugaring :: Gen => ( & [ ] , & [ ] , None ) ,
782
664
} ;
783
665
784
- // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`.
666
+ let output =
667
+ return_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
668
+
785
669
let fn_decl = self . arena . alloc ( hir:: FnDecl {
786
- inputs : arena_vec ! [ self ; input_ty ] ,
670
+ inputs,
787
671
output,
788
672
c_variadic : false ,
789
673
implicit_self : hir:: ImplicitSelfKind :: None ,
790
674
lifetime_elision_allowed : false ,
791
675
} ) ;
792
676
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
677
let body = self . lower_body ( move |this| {
812
678
this. coroutine_kind = Some ( coroutine_kind) ;
813
679
814
680
let old_ctx = this. task_context ;
815
- this. task_context = Some ( task_context_hid) ;
681
+ if task_context. is_some ( ) {
682
+ this. task_context = task_context;
683
+ }
816
684
let res = body ( this) ;
817
685
this. task_context = old_ctx;
686
+
818
687
( params, res)
819
688
} ) ;
820
689
821
- // `static |_task_context| -> <ret_ty > { body }`:
690
+ // `static |< _task_context?> | -> <return_ty > { < body> }`:
822
691
hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
823
692
def_id : self . local_def_id ( closure_node_id) ,
824
693
binder : hir:: ClosureBinder :: Default ,
@@ -1203,11 +1072,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
1203
1072
None
1204
1073
} ;
1205
1074
1206
- let async_body = this. make_async_expr (
1075
+ let async_body = this. make_desugared_coroutine_expr (
1207
1076
capture_clause,
1208
1077
inner_closure_id,
1209
1078
async_ret_ty,
1210
1079
body. span ,
1080
+ hir:: CoroutineDesugaring :: Async ,
1211
1081
hir:: CoroutineSource :: Closure ,
1212
1082
|this| this. with_new_scopes ( fn_decl_span, |this| this. lower_expr_mut ( body) ) ,
1213
1083
) ;
0 commit comments