@@ -825,6 +825,50 @@ impl<'a> LoweringContext<'a> {
825825 result
826826 }
827827
828+ // Takes the body of an async function/closure, or an async block, and
829+ // lowers it to a generator wrapped in a ::std::raw::GenFuture adapter.
830+ //
831+ // This makes it evaluate to a Future.
832+ //
833+ // For example, this:
834+ // async { ... }
835+ // Becomes:
836+ //
837+ // ::std::raw::GenFuture(|| { ... })
838+ //
839+ // TODO: Visit body and make sure it contains no bare `yield` statements.
840+ fn make_async_expr ( & mut self , body : hir:: Expr ) -> hir:: Expr {
841+ let span = body. span ;
842+
843+ // Construct a generator around body
844+ let generator = {
845+ let decl = P ( hir:: FnDecl {
846+ inputs : hir_vec ! [ ] ,
847+ output : hir:: DefaultReturn ( span) ,
848+ variadic : false ,
849+ has_implicit_self : false ,
850+ } ) ;
851+ let body_id = {
852+ let prev = mem:: replace ( & mut self . is_generator , true ) ;
853+ let r = self . record_body ( body, None ) ;
854+ self . is_generator = prev;
855+ r
856+ } ;
857+ let LoweredNodeId { node_id, hir_id } = self . next_id ( ) ;
858+ hir:: Expr {
859+ id : node_id,
860+ node : hir:: ExprClosure ( hir:: CaptureByValue , decl, body_id, span,
861+ Some ( hir:: GeneratorMovability :: Static ) ) ,
862+ attrs : ThinVec :: new ( ) ,
863+ span, hir_id,
864+ }
865+ } ;
866+
867+ let gen_future = self . expr_std_path ( span, & [ "raw" , "GenFuture" ] , ThinVec :: new ( ) ) ;
868+ self . expr_call ( span, P ( gen_future) , hir_vec ! [ generator] )
869+ }
870+
871+
828872 fn lower_body < F > ( & mut self , decl : Option < & FnDecl > , f : F ) -> hir:: BodyId
829873 where
830874 F : FnOnce ( & mut LoweringContext ) -> hir:: Expr ,
@@ -2313,7 +2357,10 @@ impl<'a> LoweringContext<'a> {
23132357 self . with_new_scopes ( |this| {
23142358 let body_id = this. lower_body ( Some ( decl) , |this| {
23152359 let body = this. lower_block ( body, false ) ;
2316- this. expr_block ( body, ThinVec :: new ( ) )
2360+ let expr = this. expr_block ( body, ThinVec :: new ( ) ) ;
2361+ if header. asyncness == IsAsync :: Async {
2362+ this. make_async_expr ( expr)
2363+ } else { expr }
23172364 } ) ;
23182365 let fn_ret_transform: & FnRetTransform = match header. asyncness {
23192366 IsAsync :: Async => & AsyncFunctionRet ,
@@ -2608,7 +2655,10 @@ impl<'a> LoweringContext<'a> {
26082655 TraitItemKind :: Method ( ref sig, Some ( ref body) ) => {
26092656 let body_id = this. lower_body ( Some ( & sig. decl ) , |this| {
26102657 let body = this. lower_block ( body, false ) ;
2611- this. expr_block ( body, ThinVec :: new ( ) )
2658+ let expr = this. expr_block ( body, ThinVec :: new ( ) ) ;
2659+ if sig. header . asyncness == IsAsync :: Async {
2660+ this. make_async_expr ( expr)
2661+ } else { expr }
26122662 } ) ;
26132663
26142664 this. add_in_band_defs (
@@ -2691,7 +2741,10 @@ impl<'a> LoweringContext<'a> {
26912741 ImplItemKind :: Method ( ref sig, ref body) => {
26922742 let body_id = this. lower_body ( Some ( & sig. decl ) , |this| {
26932743 let body = this. lower_block ( body, false ) ;
2694- this. expr_block ( body, ThinVec :: new ( ) )
2744+ let e = this. expr_block ( body, ThinVec :: new ( ) ) ;
2745+ if sig. header . asyncness == IsAsync :: Async {
2746+ this. make_async_expr ( e)
2747+ } else { e }
26952748 } ) ;
26962749 let impl_trait_return_allow = !this. is_in_trait_impl ;
26972750
@@ -3203,7 +3256,9 @@ impl<'a> LoweringContext<'a> {
32033256 let body_id = this. lower_body ( Some ( decl) , |this| {
32043257 let e = this. lower_expr ( body) ;
32053258 is_generator = this. is_generator ;
3206- e
3259+ if asyncness == IsAsync :: Async {
3260+ this. make_async_expr ( e)
3261+ } else { e }
32073262 } ) ;
32083263 let generator_option = if is_generator {
32093264 if !decl. inputs . is_empty ( ) {
@@ -3245,9 +3300,15 @@ impl<'a> LoweringContext<'a> {
32453300 } )
32463301 }
32473302 ExprKind :: Block ( ref blk, opt_label) => {
3248- hir:: ExprBlock ( self . lower_block ( blk,
3249- opt_label. is_some ( ) ) ,
3250- self . lower_label ( opt_label) )
3303+ let blk = self . lower_block ( blk,
3304+ opt_label. is_some ( ) ) ;
3305+ let opt_label = self . lower_label ( opt_label) ;
3306+ hir:: ExprBlock ( blk, opt_label)
3307+ }
3308+ ExprKind :: Async ( ref blk) => {
3309+ let blk = self . lower_block ( blk, false ) ;
3310+ let expr = self . expr ( blk. span , hir:: ExprBlock ( blk, None ) , ThinVec :: new ( ) ) ;
3311+ return self . make_async_expr ( expr) ;
32513312 }
32523313 ExprKind :: Assign ( ref el, ref er) => {
32533314 hir:: ExprAssign ( P ( self . lower_expr ( el) ) , P ( self . lower_expr ( er) ) )
0 commit comments