@@ -10,7 +10,6 @@ use rustc_hir as hir;
10
10
use rustc_hir:: def:: Res ;
11
11
use rustc_span:: source_map:: { respan, DesugaringKind , Span , Spanned } ;
12
12
use rustc_span:: symbol:: { sym, Symbol } ;
13
- use rustc_span:: DUMMY_SP ;
14
13
15
14
impl < ' hir > LoweringContext < ' _ , ' hir > {
16
15
fn lower_exprs ( & mut self , exprs : & [ AstP < Expr > ] ) -> & ' hir [ hir:: Expr < ' hir > ] {
@@ -471,6 +470,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
471
470
}
472
471
}
473
472
473
+ /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
474
+ ///
475
+ /// This results in:
476
+ ///
477
+ /// ```text
478
+ /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
479
+ /// <body>
480
+ /// })
481
+ /// ```
474
482
pub ( super ) fn make_async_expr (
475
483
& mut self ,
476
484
capture_clause : CaptureBy ,
@@ -481,46 +489,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
481
489
body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
482
490
) -> hir:: ExprKind < ' hir > {
483
491
let output = match ret_ty {
484
- Some ( ty) => FnRetTy :: Ty ( ty ) ,
485
- None => FnRetTy :: Default ( span) ,
492
+ Some ( ty) => hir :: FnRetTy :: Return ( self . lower_ty ( & ty , ImplTraitContext :: disallowed ( ) ) ) ,
493
+ None => hir :: FnRetTy :: DefaultReturn ( span) ,
486
494
} ;
487
495
488
- let task_context_id = self . resolver . next_node_id ( ) ;
489
- let task_context_hid = self . lower_node_id ( task_context_id) ;
496
+ // Resume argument type. We let the compiler infer this to simplify the lowering. It is
497
+ // fully constrained by `future::from_generator`.
498
+ let input_ty = hir:: Ty { hir_id : self . next_id ( ) , kind : hir:: TyKind :: Infer , span } ;
490
499
491
- let arg_ty = Ty { id : self . resolver . next_node_id ( ) , kind : TyKind :: Infer , span : DUMMY_SP } ;
492
- let arg_pat = Pat {
493
- id : task_context_id,
494
- kind : PatKind :: Ident (
495
- BindingMode :: ByValue ( Mutability :: Mut ) ,
496
- Ident :: with_dummy_span ( sym:: _task_context) ,
497
- None ,
498
- ) ,
499
- span : DUMMY_SP ,
500
- } ;
501
- let ast_decl = FnDecl {
502
- inputs : vec ! [ Param {
503
- attrs: AttrVec :: new( ) ,
504
- ty: AstP ( arg_ty) ,
505
- pat: AstP ( arg_pat) ,
506
- id: self . resolver. next_node_id( ) ,
507
- span: DUMMY_SP ,
508
- is_placeholder: false ,
509
- } ] ,
500
+ // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
501
+ let decl = self . arena . alloc ( hir:: FnDecl {
502
+ inputs : arena_vec ! [ self ; input_ty] ,
510
503
output,
511
- } ;
512
- let decl = self . lower_fn_decl ( & ast_decl, None , /* impl trait allowed */ false , None ) ;
513
- let body_id = self . lower_fn_body ( & ast_decl, |this| {
504
+ c_variadic : false ,
505
+ implicit_self : hir:: ImplicitSelfKind :: None ,
506
+ } ) ;
507
+
508
+ // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
509
+ let ( pat, task_context_hid) = self . pat_ident_binding_mode (
510
+ span,
511
+ Ident :: with_dummy_span ( sym:: _task_context) ,
512
+ hir:: BindingAnnotation :: Mutable ,
513
+ ) ;
514
+ let param = hir:: Param { attrs : & [ ] , hir_id : self . next_id ( ) , pat, span } ;
515
+ let params = arena_vec ! [ self ; param] ;
516
+
517
+ let body_id = self . lower_body ( move |this| {
514
518
this. generator_kind = Some ( hir:: GeneratorKind :: Async ( async_gen_kind) ) ;
515
519
516
520
let old_ctx = this. task_context ;
517
521
this. task_context = Some ( task_context_hid) ;
518
522
let res = body ( this) ;
519
523
this. task_context = old_ctx;
520
- res
524
+ ( params , res)
521
525
} ) ;
522
526
523
- // `static |task_context | -> <ret_ty> { body }`:
527
+ // `static |_task_context | -> <ret_ty> { body }`:
524
528
let generator_kind = hir:: ExprKind :: Closure (
525
529
capture_clause,
526
530
decl,
0 commit comments