@@ -448,10 +448,9 @@ impl<'a> LoweringContext<'a> {
448
448
impl < ' lcx , ' interner > Visitor < ' lcx > for MiscCollector < ' lcx , ' interner > {
449
449
fn visit_pat ( & mut self , p : & ' lcx Pat ) {
450
450
match p. node {
451
- // Doesn't generate a Hir node
451
+ // Doesn't generate a HIR node
452
452
PatKind :: Paren ( ..) => { } ,
453
453
_ => {
454
-
455
454
if let Some ( owner) = self . hir_id_owner {
456
455
self . lctx . lower_node_id_with_owner ( p. id , owner) ;
457
456
}
@@ -461,6 +460,32 @@ impl<'a> LoweringContext<'a> {
461
460
visit:: walk_pat ( self , p)
462
461
}
463
462
463
+ fn visit_fn ( & mut self , fk : visit:: FnKind < ' lcx > , fd : & ' lcx FnDecl , s : Span , _: NodeId ) {
464
+ if fk. header ( ) . map ( |h| h. asyncness . node . is_async ( ) ) . unwrap_or ( false ) {
465
+ // Don't visit the original pattern for async functions as it will be
466
+ // replaced.
467
+ for arg in & fd. inputs {
468
+ if let ArgSource :: AsyncFn ( pat) = & arg. source { self . visit_pat ( pat) ; }
469
+ self . visit_ty ( & arg. ty )
470
+ }
471
+ self . visit_fn_ret_ty ( & fd. output ) ;
472
+
473
+ match fk {
474
+ visit:: FnKind :: ItemFn ( _, decl, _, body) => {
475
+ self . visit_fn_header ( decl) ;
476
+ self . visit_block ( body)
477
+ } ,
478
+ visit:: FnKind :: Method ( _, sig, _, body) => {
479
+ self . visit_fn_header ( & sig. header ) ;
480
+ self . visit_block ( body)
481
+ } ,
482
+ visit:: FnKind :: Closure ( body) => self . visit_expr ( body) ,
483
+ }
484
+ } else {
485
+ visit:: walk_fn ( self , fk, fd, s)
486
+ }
487
+ }
488
+
464
489
fn visit_item ( & mut self , item : & ' lcx Item ) {
465
490
let hir_id = self . lctx . allocate_hir_id_counter ( item. id ) . hir_id ;
466
491
@@ -784,12 +809,10 @@ impl<'a> LoweringContext<'a> {
784
809
} )
785
810
}
786
811
787
- fn record_body ( & mut self , value : hir:: Expr , decl : Option < & FnDecl > ) -> hir:: BodyId {
812
+ fn record_body ( & mut self , value : hir:: Expr , arguments : HirVec < hir :: Arg > ) -> hir:: BodyId {
788
813
let body = hir:: Body {
789
- arguments : decl. map_or ( hir_vec ! [ ] , |decl| {
790
- decl. inputs . iter ( ) . map ( |x| self . lower_arg ( x) ) . collect ( )
791
- } ) ,
792
814
is_generator : self . is_generator ,
815
+ arguments,
793
816
value,
794
817
} ;
795
818
let id = body. id ( ) ;
@@ -1112,11 +1135,10 @@ impl<'a> LoweringContext<'a> {
1112
1135
capture_clause : CaptureBy ,
1113
1136
closure_node_id : NodeId ,
1114
1137
ret_ty : Option < & Ty > ,
1138
+ span : Span ,
1115
1139
body : impl FnOnce ( & mut LoweringContext < ' _ > ) -> hir:: Expr ,
1116
1140
) -> hir:: ExprKind {
1117
1141
let prev_is_generator = mem:: replace ( & mut self . is_generator , true ) ;
1118
- let body_expr = body ( self ) ;
1119
- let span = body_expr. span ;
1120
1142
let output = match ret_ty {
1121
1143
Some ( ty) => FunctionRetTy :: Ty ( P ( ty. clone ( ) ) ) ,
1122
1144
None => FunctionRetTy :: Default ( span) ,
@@ -1126,7 +1148,11 @@ impl<'a> LoweringContext<'a> {
1126
1148
output,
1127
1149
c_variadic : false
1128
1150
} ;
1129
- let body_id = self . record_body ( body_expr, Some ( & decl) ) ;
1151
+ // Lower the arguments before the body otherwise the body will call `lower_def` expecting
1152
+ // the argument to have been assigned an id already.
1153
+ let arguments = self . lower_args ( Some ( & decl) ) ;
1154
+ let body_expr = body ( self ) ;
1155
+ let body_id = self . record_body ( body_expr, arguments) ;
1130
1156
self . is_generator = prev_is_generator;
1131
1157
1132
1158
let capture_clause = self . lower_capture_clause ( capture_clause) ;
@@ -1157,8 +1183,9 @@ impl<'a> LoweringContext<'a> {
1157
1183
F : FnOnce ( & mut LoweringContext < ' _ > ) -> hir:: Expr ,
1158
1184
{
1159
1185
let prev = mem:: replace ( & mut self . is_generator , false ) ;
1186
+ let arguments = self . lower_args ( decl) ;
1160
1187
let result = f ( self ) ;
1161
- let r = self . record_body ( result, decl ) ;
1188
+ let r = self . record_body ( result, arguments ) ;
1162
1189
self . is_generator = prev;
1163
1190
return r;
1164
1191
}
@@ -2224,22 +2251,41 @@ impl<'a> LoweringContext<'a> {
2224
2251
init : l. init . as_ref ( ) . map ( |e| P ( self . lower_expr ( e) ) ) ,
2225
2252
span : l. span ,
2226
2253
attrs : l. attrs . clone ( ) ,
2227
- source : hir :: LocalSource :: Normal ,
2254
+ source : self . lower_local_source ( l . source ) ,
2228
2255
} , ids)
2229
2256
}
2230
2257
2258
+ fn lower_local_source ( & mut self , ls : LocalSource ) -> hir:: LocalSource {
2259
+ match ls {
2260
+ LocalSource :: Normal => hir:: LocalSource :: Normal ,
2261
+ LocalSource :: AsyncFn => hir:: LocalSource :: AsyncFn ,
2262
+ }
2263
+ }
2264
+
2231
2265
fn lower_mutability ( & mut self , m : Mutability ) -> hir:: Mutability {
2232
2266
match m {
2233
2267
Mutability :: Mutable => hir:: MutMutable ,
2234
2268
Mutability :: Immutable => hir:: MutImmutable ,
2235
2269
}
2236
2270
}
2237
2271
2272
+ fn lower_args ( & mut self , decl : Option < & FnDecl > ) -> HirVec < hir:: Arg > {
2273
+ decl. map_or ( hir_vec ! [ ] , |decl| decl. inputs . iter ( ) . map ( |x| self . lower_arg ( x) ) . collect ( ) )
2274
+ }
2275
+
2238
2276
fn lower_arg ( & mut self , arg : & Arg ) -> hir:: Arg {
2239
2277
let LoweredNodeId { node_id : _, hir_id } = self . lower_node_id ( arg. id ) ;
2240
2278
hir:: Arg {
2241
2279
hir_id,
2242
2280
pat : self . lower_pat ( & arg. pat ) ,
2281
+ source : self . lower_arg_source ( & arg. source ) ,
2282
+ }
2283
+ }
2284
+
2285
+ fn lower_arg_source ( & mut self , source : & ArgSource ) -> hir:: ArgSource {
2286
+ match source {
2287
+ ArgSource :: Normal => hir:: ArgSource :: Normal ,
2288
+ ArgSource :: AsyncFn ( pat) => hir:: ArgSource :: AsyncFn ( self . lower_pat ( pat) ) ,
2243
2289
}
2244
2290
}
2245
2291
@@ -2993,15 +3039,21 @@ impl<'a> LoweringContext<'a> {
2993
3039
fn lower_async_body (
2994
3040
& mut self ,
2995
3041
decl : & FnDecl ,
2996
- asyncness : IsAsync ,
3042
+ asyncness : & IsAsync ,
2997
3043
body : & Block ,
2998
3044
) -> hir:: BodyId {
2999
- self . lower_body ( Some ( decl) , |this| {
3000
- if let IsAsync :: Async { closure_id, .. } = asyncness {
3045
+ self . lower_body ( Some ( & decl) , |this| {
3046
+ if let IsAsync :: Async { closure_id, ref arguments, .. } = asyncness {
3047
+ let mut body = body. clone ( ) ;
3048
+
3049
+ for a in arguments. iter ( ) . rev ( ) {
3050
+ body. stmts . insert ( 0 , a. stmt . clone ( ) ) ;
3051
+ }
3052
+
3001
3053
let async_expr = this. make_async_expr (
3002
- CaptureBy :: Value , closure_id, None ,
3054
+ CaptureBy :: Value , * closure_id, None , body . span ,
3003
3055
|this| {
3004
- let body = this. lower_block ( body, false ) ;
3056
+ let body = this. lower_block ( & body, false ) ;
3005
3057
this. expr_block ( body, ThinVec :: new ( ) )
3006
3058
} ) ;
3007
3059
this. expr ( body. span , async_expr, ThinVec :: new ( ) )
@@ -3060,26 +3112,42 @@ impl<'a> LoweringContext<'a> {
3060
3112
value
3061
3113
)
3062
3114
}
3063
- ItemKind :: Fn ( ref decl, header, ref generics, ref body) => {
3115
+ ItemKind :: Fn ( ref decl, ref header, ref generics, ref body) => {
3064
3116
let fn_def_id = self . resolver . definitions ( ) . local_def_id ( id) ;
3065
3117
self . with_new_scopes ( |this| {
3066
- // Note: we don't need to change the return type from `T` to
3067
- // `impl Future<Output = T>` here because lower_body
3068
- // only cares about the input argument patterns in the function
3069
- // declaration (decl), not the return types.
3070
- let body_id = this. lower_async_body ( decl, header. asyncness . node , body) ;
3118
+ let mut lower_fn = |decl : & FnDecl | {
3119
+ // Note: we don't need to change the return type from `T` to
3120
+ // `impl Future<Output = T>` here because lower_body
3121
+ // only cares about the input argument patterns in the function
3122
+ // declaration (decl), not the return types.
3123
+ let body_id = this. lower_async_body ( & decl, & header. asyncness . node , body) ;
3124
+
3125
+ let ( generics, fn_decl) = this. add_in_band_defs (
3126
+ generics,
3127
+ fn_def_id,
3128
+ AnonymousLifetimeMode :: PassThrough ,
3129
+ |this, idty| this. lower_fn_decl (
3130
+ & decl,
3131
+ Some ( ( fn_def_id, idty) ) ,
3132
+ true ,
3133
+ header. asyncness . node . opt_return_id ( )
3134
+ ) ,
3135
+ ) ;
3071
3136
3072
- let ( generics, fn_decl) = this. add_in_band_defs (
3073
- generics,
3074
- fn_def_id,
3075
- AnonymousLifetimeMode :: PassThrough ,
3076
- |this, idty| this. lower_fn_decl (
3077
- decl,
3078
- Some ( ( fn_def_id, idty) ) ,
3079
- true ,
3080
- header. asyncness . node . opt_return_id ( )
3081
- ) ,
3082
- ) ;
3137
+ ( body_id, generics, fn_decl)
3138
+ } ;
3139
+
3140
+ let ( body_id, generics, fn_decl) = if let IsAsync :: Async {
3141
+ arguments, ..
3142
+ } = & header. asyncness . node {
3143
+ let mut decl = decl. clone ( ) ;
3144
+ // Replace the arguments of this async function with the generated
3145
+ // arguments that will be moved into the closure.
3146
+ decl. inputs = arguments. clone ( ) . drain ( ..) . map ( |a| a. arg ) . collect ( ) ;
3147
+ lower_fn ( & decl)
3148
+ } else {
3149
+ lower_fn ( decl)
3150
+ } ;
3083
3151
3084
3152
hir:: ItemKind :: Fn (
3085
3153
fn_decl,
@@ -3558,15 +3626,33 @@ impl<'a> LoweringContext<'a> {
3558
3626
)
3559
3627
}
3560
3628
ImplItemKind :: Method ( ref sig, ref body) => {
3561
- let body_id = self . lower_async_body ( & sig. decl , sig. header . asyncness . node , body) ;
3562
- let impl_trait_return_allow = !self . is_in_trait_impl ;
3563
- let ( generics, sig) = self . lower_method_sig (
3564
- & i. generics ,
3565
- sig,
3566
- impl_item_def_id,
3567
- impl_trait_return_allow,
3568
- sig. header . asyncness . node . opt_return_id ( ) ,
3569
- ) ;
3629
+ let mut lower_method = |sig : & MethodSig | {
3630
+ let body_id = self . lower_async_body (
3631
+ & sig. decl , & sig. header . asyncness . node , body
3632
+ ) ;
3633
+ let impl_trait_return_allow = !self . is_in_trait_impl ;
3634
+ let ( generics, sig) = self . lower_method_sig (
3635
+ & i. generics ,
3636
+ sig,
3637
+ impl_item_def_id,
3638
+ impl_trait_return_allow,
3639
+ sig. header . asyncness . node . opt_return_id ( ) ,
3640
+ ) ;
3641
+ ( body_id, generics, sig)
3642
+ } ;
3643
+
3644
+ let ( body_id, generics, sig) = if let IsAsync :: Async {
3645
+ ref arguments, ..
3646
+ } = sig. header . asyncness . node {
3647
+ let mut sig = sig. clone ( ) ;
3648
+ // Replace the arguments of this async function with the generated
3649
+ // arguments that will be moved into the closure.
3650
+ sig. decl . inputs = arguments. clone ( ) . drain ( ..) . map ( |a| a. arg ) . collect ( ) ;
3651
+ lower_method ( & sig)
3652
+ } else {
3653
+ lower_method ( sig)
3654
+ } ;
3655
+
3570
3656
( generics, hir:: ImplItemKind :: Method ( sig, body_id) )
3571
3657
}
3572
3658
ImplItemKind :: Type ( ref ty) => (
@@ -3760,7 +3846,7 @@ impl<'a> LoweringContext<'a> {
3760
3846
impl_trait_return_allow : bool ,
3761
3847
is_async : Option < NodeId > ,
3762
3848
) -> ( hir:: Generics , hir:: MethodSig ) {
3763
- let header = self . lower_fn_header ( sig. header ) ;
3849
+ let header = self . lower_fn_header ( & sig. header ) ;
3764
3850
let ( generics, decl) = self . add_in_band_defs (
3765
3851
generics,
3766
3852
fn_def_id,
@@ -3782,10 +3868,10 @@ impl<'a> LoweringContext<'a> {
3782
3868
}
3783
3869
}
3784
3870
3785
- fn lower_fn_header ( & mut self , h : FnHeader ) -> hir:: FnHeader {
3871
+ fn lower_fn_header ( & mut self , h : & FnHeader ) -> hir:: FnHeader {
3786
3872
hir:: FnHeader {
3787
3873
unsafety : self . lower_unsafety ( h. unsafety ) ,
3788
- asyncness : self . lower_asyncness ( h. asyncness . node ) ,
3874
+ asyncness : self . lower_asyncness ( & h. asyncness . node ) ,
3789
3875
constness : self . lower_constness ( h. constness ) ,
3790
3876
abi : h. abi ,
3791
3877
}
@@ -3805,7 +3891,7 @@ impl<'a> LoweringContext<'a> {
3805
3891
}
3806
3892
}
3807
3893
3808
- fn lower_asyncness ( & mut self , a : IsAsync ) -> hir:: IsAsync {
3894
+ fn lower_asyncness ( & mut self , a : & IsAsync ) -> hir:: IsAsync {
3809
3895
match a {
3810
3896
IsAsync :: Async { .. } => hir:: IsAsync :: Async ,
3811
3897
IsAsync :: NotAsync => hir:: IsAsync :: NotAsync ,
@@ -4110,15 +4196,15 @@ impl<'a> LoweringContext<'a> {
4110
4196
hir:: MatchSource :: Normal ,
4111
4197
) ,
4112
4198
ExprKind :: Async ( capture_clause, closure_node_id, ref block) => {
4113
- self . make_async_expr ( capture_clause, closure_node_id, None , |this| {
4199
+ self . make_async_expr ( capture_clause, closure_node_id, None , block . span , |this| {
4114
4200
this. with_new_scopes ( |this| {
4115
4201
let block = this. lower_block ( block, false ) ;
4116
4202
this. expr_block ( block, ThinVec :: new ( ) )
4117
4203
} )
4118
4204
} )
4119
4205
}
4120
4206
ExprKind :: Closure (
4121
- capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
4207
+ capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span
4122
4208
) => {
4123
4209
if let IsAsync :: Async { closure_id, .. } = asyncness {
4124
4210
let outer_decl = FnDecl {
@@ -4156,7 +4242,7 @@ impl<'a> LoweringContext<'a> {
4156
4242
Some ( & * * ty)
4157
4243
} else { None } ;
4158
4244
let async_body = this. make_async_expr (
4159
- capture_clause, closure_id, async_ret_ty,
4245
+ capture_clause, * closure_id, async_ret_ty, body . span ,
4160
4246
|this| {
4161
4247
this. with_new_scopes ( |this| this. lower_expr ( body) )
4162
4248
} ) ;
0 commit comments