@@ -183,14 +183,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
183183 self . arena . alloc_from_iter ( arms. iter ( ) . map ( |x| self . lower_arm ( x) ) ) ,
184184 hir:: MatchSource :: Normal ,
185185 ) ,
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- ) ,
194186 ExprKind :: Await ( expr, await_kw_span) => self . lower_expr_await ( * await_kw_span, expr) ,
195187 ExprKind :: Closure ( box Closure {
196188 binder,
@@ -226,6 +218,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
226218 * fn_arg_span,
227219 ) ,
228220 } ,
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+ }
229237 ExprKind :: Block ( blk, opt_label) => {
230238 let opt_label = self . lower_label ( * opt_label) ;
231239 hir:: ExprKind :: Block ( self . lower_block ( blk, opt_label. is_some ( ) ) , opt_label)
@@ -313,23 +321,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
313321 rest,
314322 )
315323 }
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- ) ,
333324 ExprKind :: Yield ( opt_expr) => self . lower_expr_yield ( e. span , opt_expr. as_deref ( ) ) ,
334325 ExprKind :: Err => {
335326 hir:: ExprKind :: Err ( self . dcx ( ) . span_delayed_bug ( e. span , "lowered ExprKind::Err" ) )
@@ -612,213 +603,91 @@ impl<'hir> LoweringContext<'_, 'hir> {
612603 hir:: Arm { hir_id, pat, guard, body, span }
613604 }
614605
615- /// Lower an `async` construct to a coroutine that implements `Future` .
606+ /// Lower/desugar a coroutine construct .
616607 ///
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`.
699609 ///
700610 /// This results in:
701611 ///
702612 /// ```text
703- /// static move? |() | -> () {
613+ /// static move? |<_task_context?> | -> <return_ty> {
704614 /// <body>
705615 /// }
706616 /// ```
707- pub ( super ) fn make_gen_expr (
617+ pub ( super ) fn make_desugared_coroutine_expr (
708618 & mut self ,
709619 capture_clause : CaptureBy ,
710620 closure_node_id : NodeId ,
711- _yield_ty : Option < hir:: FnRetTy < ' hir > > ,
621+ return_ty : Option < hir:: FnRetTy < ' hir > > ,
712622 span : Span ,
623+ desugaring_kind : hir:: CoroutineDesugaring ,
713624 coroutine_source : hir:: CoroutineSource ,
714625 body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
715626 ) -> 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] ;
750646
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] ;
770660
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 ) ,
782664 } ;
783665
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+
785669 let fn_decl = self . arena . alloc ( hir:: FnDecl {
786- inputs : arena_vec ! [ self ; input_ty ] ,
670+ inputs,
787671 output,
788672 c_variadic : false ,
789673 implicit_self : hir:: ImplicitSelfKind :: None ,
790674 lifetime_elision_allowed : false ,
791675 } ) ;
792676
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- ) ;
811677 let body = self . lower_body ( move |this| {
812678 this. coroutine_kind = Some ( coroutine_kind) ;
813679
814680 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+ }
816684 let res = body ( this) ;
817685 this. task_context = old_ctx;
686+
818687 ( params, res)
819688 } ) ;
820689
821- // `static |_task_context| -> <ret_ty > { body }`:
690+ // `static |< _task_context?> | -> <return_ty > { < body> }`:
822691 hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
823692 def_id : self . local_def_id ( closure_node_id) ,
824693 binder : hir:: ClosureBinder :: Default ,
@@ -1203,11 +1072,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
12031072 None
12041073 } ;
12051074
1206- let async_body = this. make_async_expr (
1075+ let async_body = this. make_desugared_coroutine_expr (
12071076 capture_clause,
12081077 inner_closure_id,
12091078 async_ret_ty,
12101079 body. span ,
1080+ hir:: CoroutineDesugaring :: Async ,
12111081 hir:: CoroutineSource :: Closure ,
12121082 |this| this. with_new_scopes ( fn_decl_span, |this| this. lower_expr_mut ( body) ) ,
12131083 ) ;
0 commit comments