@@ -183,7 +183,7 @@ 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 :: Async ( capture_clause,  block)  => self . make_async_expr ( 
186+                 ExprKind :: Gen ( capture_clause,  block,   GenBlockKind :: Async )  => self . make_async_expr ( 
187187                    * capture_clause, 
188188                    e. id , 
189189                    None , 
@@ -317,6 +317,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
317317                        rest, 
318318                    ) 
319319                } 
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:: CoroutineSource :: Block , 
326+                     |this| this. with_new_scopes ( |this| this. lower_block_expr ( block) ) , 
327+                 ) , 
320328                ExprKind :: Yield ( opt_expr)  => self . lower_expr_yield ( e. span ,  opt_expr. as_deref ( ) ) , 
321329                ExprKind :: Err  => hir:: ExprKind :: Err ( 
322330                    self . tcx . sess . delay_span_bug ( e. span ,  "lowered ExprKind::Err" ) , 
@@ -661,6 +669,57 @@ impl<'hir> LoweringContext<'_, 'hir> {
661669        } ) ) 
662670    } 
663671
672+     /// Lower a `gen` construct to a generator that implements `Iterator`. 
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+         gen_kind :  hir:: CoroutineSource , 
688+         body :  impl  FnOnce ( & mut  Self )  -> hir:: Expr < ' hir > , 
689+     )  -> hir:: ExprKind < ' hir >  { 
690+         let  output = hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ; 
691+ 
692+         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. 
693+         let  fn_decl = self . arena . alloc ( hir:: FnDecl  { 
694+             inputs :  & [ ] , 
695+             output, 
696+             c_variadic :  false , 
697+             implicit_self :  hir:: ImplicitSelfKind :: None , 
698+             lifetime_elision_allowed :  false , 
699+         } ) ; 
700+ 
701+         let  body = self . lower_body ( move  |this| { 
702+             this. coroutine_kind  = Some ( hir:: CoroutineKind :: Gen ( gen_kind) ) ; 
703+ 
704+             let  res = body ( this) ; 
705+             ( & [ ] ,  res) 
706+         } ) ; 
707+ 
708+         // `static |()| -> () { body }`: 
709+         hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure  { 
710+             def_id :  self . local_def_id ( closure_node_id) , 
711+             binder :  hir:: ClosureBinder :: Default , 
712+             capture_clause, 
713+             bound_generic_params :  & [ ] , 
714+             fn_decl, 
715+             body, 
716+             fn_decl_span :  self . lower_span ( span) , 
717+             fn_arg_span :  None , 
718+             movability :  Some ( Movability :: Movable ) , 
719+             constness :  hir:: Constness :: NotConst , 
720+         } ) ) 
721+     } 
722+ 
664723    /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to 
665724     /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled. 
666725     pub ( super )  fn  maybe_forward_track_caller ( 
@@ -712,7 +771,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
712771        let  full_span = expr. span . to ( await_kw_span) ; 
713772        match  self . coroutine_kind  { 
714773            Some ( hir:: CoroutineKind :: Async ( _) )  => { } 
715-             Some ( hir:: CoroutineKind :: Coroutine )  | None  => { 
774+             Some ( hir:: CoroutineKind :: Coroutine )  | Some ( hir :: CoroutineKind :: Gen ( _ ) )  |  None  => { 
716775                self . tcx . sess . emit_err ( AwaitOnlyInAsyncFnAndBlocks  { 
717776                    await_kw_span, 
718777                    item_span :  self . current_item , 
@@ -936,8 +995,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
936995                } 
937996                Some ( movability) 
938997            } 
939-             Some ( hir:: CoroutineKind :: Async ( _) )  => { 
940-                 panic ! ( "non-`async` closure body turned `async` during lowering" ) ; 
998+             Some ( hir:: CoroutineKind :: Gen ( _ ) )  |  Some ( hir :: CoroutineKind :: Async ( _) )  => { 
999+                 panic ! ( "non-`async`/`gen`  closure body turned `async`/`gen ` during lowering" ) ; 
9411000            } 
9421001            None  => { 
9431002                if  movability == Movability :: Static  { 
@@ -1445,11 +1504,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
14451504
14461505    fn  lower_expr_yield ( & mut  self ,  span :  Span ,  opt_expr :  Option < & Expr > )  -> hir:: ExprKind < ' hir >  { 
14471506        match  self . coroutine_kind  { 
1448-             Some ( hir:: CoroutineKind :: Coroutine )  => { } 
1507+             Some ( hir:: CoroutineKind :: Gen ( _ ) )  => { } 
14491508            Some ( hir:: CoroutineKind :: Async ( _) )  => { 
14501509                self . tcx . sess . emit_err ( AsyncCoroutinesNotSupported  {  span } ) ; 
14511510            } 
1452-             None  => self . coroutine_kind  = Some ( hir:: CoroutineKind :: Coroutine ) , 
1511+             Some ( hir:: CoroutineKind :: Coroutine )  | None  => { 
1512+                 if  !self . tcx . features ( ) . coroutines  { 
1513+                     rustc_session:: parse:: feature_err ( 
1514+                         & self . tcx . sess . parse_sess , 
1515+                         sym:: coroutines, 
1516+                         span, 
1517+                         "yield syntax is experimental" , 
1518+                     ) 
1519+                     . emit ( ) ; 
1520+                 } 
1521+                 self . coroutine_kind  = Some ( hir:: CoroutineKind :: Coroutine ) 
1522+             } 
14531523        } 
14541524
14551525        let  expr =
0 commit comments