@@ -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,94 @@ 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`.
616- ///
617- /// This results in:
606+ /// Lower/desugar a coroutine construct.
618607 ///
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) : ( & [ _ ] , & [ _ ] , _ ) = 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] ;
750649
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] ;
770663
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 )
782667 } ;
783668
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+
785672 let fn_decl = self . arena . alloc ( hir:: FnDecl {
786- inputs : arena_vec ! [ self ; input_ty ] ,
673+ inputs,
787674 output,
788675 c_variadic : false ,
789676 implicit_self : hir:: ImplicitSelfKind :: None ,
790677 lifetime_elision_allowed : false ,
791678 } ) ;
792679
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- ) ;
811680 let body = self . lower_body ( move |this| {
812681 this. coroutine_kind = Some ( coroutine_kind) ;
813682
814683 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+ }
816687 let res = body ( this) ;
817688 this. task_context = old_ctx;
689+
818690 ( params, res)
819691 } ) ;
820692
821- // `static |_task_context| -> <ret_ty > { body }`:
693+ // `static |< _task_context?> | -> <return_ty > { < body> }`:
822694 hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
823695 def_id : self . local_def_id ( closure_node_id) ,
824696 binder : hir:: ClosureBinder :: Default ,
@@ -1203,11 +1075,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
12031075 None
12041076 } ;
12051077
1206- let async_body = this. make_async_expr (
1078+ let async_body = this. make_desugared_coroutine_expr (
12071079 capture_clause,
12081080 inner_closure_id,
12091081 async_ret_ty,
12101082 body. span ,
1083+ hir:: CoroutineDesugaring :: Async ,
12111084 hir:: CoroutineSource :: Closure ,
12121085 |this| this. with_new_scopes ( fn_decl_span, |this| this. lower_expr_mut ( body) ) ,
12131086 ) ;
0 commit comments