@@ -183,7 +183,7 @@ 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 :: Async ( capture_clause, block) => self . make_async_expr (
186
+ ExprKind :: Gen ( capture_clause, block, GenBlockKind :: Async ) => self . make_async_expr (
187
187
* capture_clause,
188
188
e. id ,
189
189
None ,
@@ -317,6 +317,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
317
317
rest,
318
318
)
319
319
}
320
+ ExprKind :: Gen ( capture_clause, block, GenBlockKind :: Gen ) => self . make_gen_expr (
321
+ * capture_clause,
322
+ e. id ,
323
+ None ,
324
+ e. span ,
325
+ hir:: AsyncGeneratorKind :: Block ,
326
+ |this| this. with_new_scopes ( |this| this. lower_block_expr ( block) ) ,
327
+ ) ,
320
328
ExprKind :: Yield ( opt_expr) => self . lower_expr_yield ( e. span , opt_expr. as_deref ( ) ) ,
321
329
ExprKind :: Err => hir:: ExprKind :: Err (
322
330
self . tcx . sess . delay_span_bug ( e. span , "lowered ExprKind::Err" ) ,
@@ -661,6 +669,86 @@ impl<'hir> LoweringContext<'_, 'hir> {
661
669
} ) )
662
670
}
663
671
672
+ /// Lower a `gen` construct to a generator that implements `Future`.
673
+ ///
674
+ /// This results in:
675
+ ///
676
+ /// ```text
677
+ /// static move? |()| -> () {
678
+ /// <body>
679
+ /// }
680
+ /// ```
681
+ pub ( super ) fn make_gen_expr (
682
+ & mut self ,
683
+ capture_clause : CaptureBy ,
684
+ closure_node_id : NodeId ,
685
+ yield_ty : Option < hir:: FnRetTy < ' hir > > ,
686
+ span : Span ,
687
+ // We re-use the async enum, because we have the same cases.
688
+ // FIXME(oli-obk): rename the enum.
689
+ gen_kind : hir:: AsyncGeneratorKind ,
690
+ body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
691
+ ) -> hir:: ExprKind < ' hir > {
692
+ let output = yield_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
693
+
694
+ // Resume argument type: `ResumeTy`
695
+ let unstable_span =
696
+ self . mark_span_with_reason ( DesugaringKind :: Async , span, self . allow_gen_future . clone ( ) ) ;
697
+ let resume_ty = hir:: QPath :: LangItem ( hir:: LangItem :: ResumeTy , unstable_span, None ) ;
698
+ let input_ty = hir:: Ty {
699
+ hir_id : self . next_id ( ) ,
700
+ kind : hir:: TyKind :: Path ( resume_ty) ,
701
+ span : unstable_span,
702
+ } ;
703
+
704
+ // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
705
+ let fn_decl = self . arena . alloc ( hir:: FnDecl {
706
+ inputs : arena_vec ! [ self ; input_ty] ,
707
+ output,
708
+ c_variadic : false ,
709
+ implicit_self : hir:: ImplicitSelfKind :: None ,
710
+ lifetime_elision_allowed : false ,
711
+ } ) ;
712
+
713
+ // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
714
+ let ( pat, task_context_hid) = self . pat_ident_binding_mode (
715
+ span,
716
+ Ident :: with_dummy_span ( sym:: _task_context) ,
717
+ hir:: BindingAnnotation :: MUT ,
718
+ ) ;
719
+ let param = hir:: Param {
720
+ hir_id : self . next_id ( ) ,
721
+ pat,
722
+ ty_span : self . lower_span ( span) ,
723
+ span : self . lower_span ( span) ,
724
+ } ;
725
+ let params = arena_vec ! [ self ; param] ;
726
+
727
+ let body = self . lower_body ( move |this| {
728
+ this. generator_kind = Some ( hir:: GeneratorKind :: Iter ( gen_kind) ) ;
729
+
730
+ let old_ctx = this. task_context ;
731
+ this. task_context = Some ( task_context_hid) ;
732
+ let res = body ( this) ;
733
+ this. task_context = old_ctx;
734
+ ( params, res)
735
+ } ) ;
736
+
737
+ // `static |_task_context| -> <ret_ty> { body }`:
738
+ hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
739
+ def_id : self . local_def_id ( closure_node_id) ,
740
+ binder : hir:: ClosureBinder :: Default ,
741
+ capture_clause,
742
+ bound_generic_params : & [ ] ,
743
+ fn_decl,
744
+ body,
745
+ fn_decl_span : self . lower_span ( span) ,
746
+ fn_arg_span : None ,
747
+ movability : Some ( hir:: Movability :: Static ) ,
748
+ constness : hir:: Constness :: NotConst ,
749
+ } ) )
750
+ }
751
+
664
752
/// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
665
753
/// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.
666
754
pub ( super ) fn maybe_forward_track_caller (
0 commit comments