@@ -825,6 +825,50 @@ impl<'a> LoweringContext<'a> {
825
825
result
826
826
}
827
827
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
+
828
872
fn lower_body < F > ( & mut self , decl : Option < & FnDecl > , f : F ) -> hir:: BodyId
829
873
where
830
874
F : FnOnce ( & mut LoweringContext ) -> hir:: Expr ,
@@ -2313,7 +2357,10 @@ impl<'a> LoweringContext<'a> {
2313
2357
self . with_new_scopes ( |this| {
2314
2358
let body_id = this. lower_body ( Some ( decl) , |this| {
2315
2359
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 }
2317
2364
} ) ;
2318
2365
let fn_ret_transform: & FnRetTransform = match header. asyncness {
2319
2366
IsAsync :: Async => & AsyncFunctionRet ,
@@ -2608,7 +2655,10 @@ impl<'a> LoweringContext<'a> {
2608
2655
TraitItemKind :: Method ( ref sig, Some ( ref body) ) => {
2609
2656
let body_id = this. lower_body ( Some ( & sig. decl ) , |this| {
2610
2657
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 }
2612
2662
} ) ;
2613
2663
2614
2664
this. add_in_band_defs (
@@ -2691,7 +2741,10 @@ impl<'a> LoweringContext<'a> {
2691
2741
ImplItemKind :: Method ( ref sig, ref body) => {
2692
2742
let body_id = this. lower_body ( Some ( & sig. decl ) , |this| {
2693
2743
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 }
2695
2748
} ) ;
2696
2749
let impl_trait_return_allow = !this. is_in_trait_impl ;
2697
2750
@@ -3203,7 +3256,9 @@ impl<'a> LoweringContext<'a> {
3203
3256
let body_id = this. lower_body ( Some ( decl) , |this| {
3204
3257
let e = this. lower_expr ( body) ;
3205
3258
is_generator = this. is_generator ;
3206
- e
3259
+ if asyncness == IsAsync :: Async {
3260
+ this. make_async_expr ( e)
3261
+ } else { e }
3207
3262
} ) ;
3208
3263
let generator_option = if is_generator {
3209
3264
if !decl. inputs . is_empty ( ) {
@@ -3245,9 +3300,15 @@ impl<'a> LoweringContext<'a> {
3245
3300
} )
3246
3301
}
3247
3302
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) ;
3251
3312
}
3252
3313
ExprKind :: Assign ( ref el, ref er) => {
3253
3314
hir:: ExprAssign ( P ( self . lower_expr ( el) ) , P ( self . lower_expr ( er) ) )
0 commit comments