1
+ use crate :: FnReturnTransformation ;
2
+
1
3
use super :: errors:: { InvalidAbi , InvalidAbiReason , InvalidAbiSuggestion , MisplacedRelaxTraitBound } ;
2
4
use super :: ResolverAstLoweringExt ;
3
5
use super :: { AstOwner , ImplTraitContext , ImplTraitPosition } ;
@@ -276,13 +278,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
276
278
// only cares about the input argument patterns in the function
277
279
// declaration (decl), not the return types.
278
280
let asyncness = header. asyncness ;
279
- let body_id =
280
- this. lower_maybe_async_body ( span, hir_id, decl, asyncness, body. as_deref ( ) ) ;
281
+ let genness = header. genness ;
282
+ let body_id = this. lower_maybe_coroutine_body (
283
+ span,
284
+ hir_id,
285
+ decl,
286
+ asyncness,
287
+ genness,
288
+ body. as_deref ( ) ,
289
+ ) ;
281
290
282
291
let itctx = ImplTraitContext :: Universal ;
283
292
let ( generics, decl) =
284
293
this. lower_generics ( generics, header. constness , id, & itctx, |this| {
285
- let ret_id = asyncness. opt_return_id ( ) ;
294
+ let ret_id = asyncness
295
+ . opt_return_id ( )
296
+ . map ( |( node_id, span) | {
297
+ crate :: FnReturnTransformation :: Async ( node_id, span)
298
+ } )
299
+ . or_else ( || match genness {
300
+ Gen :: Yes { span, closure_id : _, return_impl_trait_id } => {
301
+ Some ( crate :: FnReturnTransformation :: Iterator (
302
+ return_impl_trait_id,
303
+ span,
304
+ ) )
305
+ }
306
+ _ => None ,
307
+ } ) ;
286
308
this. lower_fn_decl ( decl, id, * fn_sig_span, FnDeclKind :: Fn , ret_id)
287
309
} ) ;
288
310
let sig = hir:: FnSig {
@@ -765,20 +787,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
765
787
sig,
766
788
i. id ,
767
789
FnDeclKind :: Trait ,
768
- asyncness. opt_return_id ( ) ,
790
+ asyncness
791
+ . opt_return_id ( )
792
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
769
793
) ;
770
794
( generics, hir:: TraitItemKind :: Fn ( sig, hir:: TraitFn :: Required ( names) ) , false )
771
795
}
772
796
AssocItemKind :: Fn ( box Fn { sig, generics, body : Some ( body) , .. } ) => {
773
797
let asyncness = sig. header . asyncness ;
774
- let body_id =
775
- self . lower_maybe_async_body ( i. span , hir_id, & sig. decl , asyncness, Some ( body) ) ;
798
+ let genness = sig. header . genness ;
799
+ let body_id = self . lower_maybe_coroutine_body (
800
+ i. span ,
801
+ hir_id,
802
+ & sig. decl ,
803
+ asyncness,
804
+ genness,
805
+ Some ( body) ,
806
+ ) ;
776
807
let ( generics, sig) = self . lower_method_sig (
777
808
generics,
778
809
sig,
779
810
i. id ,
780
811
FnDeclKind :: Trait ,
781
- asyncness. opt_return_id ( ) ,
812
+ asyncness
813
+ . opt_return_id ( )
814
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
782
815
) ;
783
816
( generics, hir:: TraitItemKind :: Fn ( sig, hir:: TraitFn :: Provided ( body_id) ) , true )
784
817
}
@@ -869,19 +902,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
869
902
AssocItemKind :: Fn ( box Fn { sig, generics, body, .. } ) => {
870
903
self . current_item = Some ( i. span ) ;
871
904
let asyncness = sig. header . asyncness ;
872
- let body_id = self . lower_maybe_async_body (
905
+ let genness = sig. header . genness ;
906
+ let body_id = self . lower_maybe_coroutine_body (
873
907
i. span ,
874
908
hir_id,
875
909
& sig. decl ,
876
910
asyncness,
911
+ genness,
877
912
body. as_deref ( ) ,
878
913
) ;
879
914
let ( generics, sig) = self . lower_method_sig (
880
915
generics,
881
916
sig,
882
917
i. id ,
883
918
if self . is_in_trait_impl { FnDeclKind :: Impl } else { FnDeclKind :: Inherent } ,
884
- asyncness. opt_return_id ( ) ,
919
+ asyncness
920
+ . opt_return_id ( )
921
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
885
922
) ;
886
923
887
924
( generics, hir:: ImplItemKind :: Fn ( sig, body_id) )
@@ -1045,16 +1082,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
1045
1082
} )
1046
1083
}
1047
1084
1048
- fn lower_maybe_async_body (
1085
+ /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or
1086
+ /// `gen {}` block as appropriate.
1087
+ fn lower_maybe_coroutine_body (
1049
1088
& mut self ,
1050
1089
span : Span ,
1051
1090
fn_id : hir:: HirId ,
1052
1091
decl : & FnDecl ,
1053
1092
asyncness : Async ,
1093
+ genness : Gen ,
1054
1094
body : Option < & Block > ,
1055
1095
) -> hir:: BodyId {
1056
- let ( closure_id, body) = match ( asyncness, body) {
1057
- ( Async :: Yes { closure_id, .. } , Some ( body) ) => ( closure_id, body) ,
1096
+ let ( closure_id, body) = match ( asyncness, genness, body) {
1097
+ // FIXME(eholk): do something reasonable for `async gen fn`. Probably that's an error
1098
+ // for now since it's not supported.
1099
+ ( Async :: Yes { closure_id, .. } , _, Some ( body) )
1100
+ | ( _, Gen :: Yes { closure_id, .. } , Some ( body) ) => ( closure_id, body) ,
1058
1101
_ => return self . lower_fn_body_block ( span, decl, body) ,
1059
1102
} ;
1060
1103
@@ -1197,44 +1240,55 @@ impl<'hir> LoweringContext<'_, 'hir> {
1197
1240
parameters. push ( new_parameter) ;
1198
1241
}
1199
1242
1200
- let async_expr = this. make_async_expr (
1201
- CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1202
- closure_id,
1203
- None ,
1204
- body. span ,
1205
- hir:: CoroutineSource :: Fn ,
1206
- |this| {
1207
- // Create a block from the user's function body:
1208
- let user_body = this. lower_block_expr ( body) ;
1243
+ let mkbody = |this : & mut LoweringContext < ' _ , ' hir > | {
1244
+ // Create a block from the user's function body:
1245
+ let user_body = this. lower_block_expr ( body) ;
1209
1246
1210
- // Transform into `drop-temps { <user-body> }`, an expression:
1211
- let desugared_span =
1212
- this. mark_span_with_reason ( DesugaringKind :: Async , user_body. span , None ) ;
1213
- let user_body =
1214
- this. expr_drop_temps ( desugared_span, this. arena . alloc ( user_body) ) ;
1247
+ // Transform into `drop-temps { <user-body> }`, an expression:
1248
+ let desugared_span =
1249
+ this. mark_span_with_reason ( DesugaringKind :: Async , user_body. span , None ) ;
1250
+ let user_body = this. expr_drop_temps ( desugared_span, this. arena . alloc ( user_body) ) ;
1215
1251
1216
- // As noted above, create the final block like
1217
- //
1218
- // ```
1219
- // {
1220
- // let $param_pattern = $raw_param;
1221
- // ...
1222
- // drop-temps { <user-body> }
1223
- // }
1224
- // ```
1225
- let body = this. block_all (
1226
- desugared_span,
1227
- this. arena . alloc_from_iter ( statements) ,
1228
- Some ( user_body) ,
1229
- ) ;
1252
+ // As noted above, create the final block like
1253
+ //
1254
+ // ```
1255
+ // {
1256
+ // let $param_pattern = $raw_param;
1257
+ // ...
1258
+ // drop-temps { <user-body> }
1259
+ // }
1260
+ // ```
1261
+ let body = this. block_all (
1262
+ desugared_span,
1263
+ this. arena . alloc_from_iter ( statements) ,
1264
+ Some ( user_body) ,
1265
+ ) ;
1230
1266
1231
- this. expr_block ( body)
1232
- } ,
1233
- ) ;
1267
+ this. expr_block ( body)
1268
+ } ;
1269
+ let coroutine_expr = match ( asyncness, genness) {
1270
+ ( Async :: Yes { .. } , _) => this. make_async_expr (
1271
+ CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1272
+ closure_id,
1273
+ None ,
1274
+ body. span ,
1275
+ hir:: CoroutineSource :: Fn ,
1276
+ mkbody,
1277
+ ) ,
1278
+ ( _, Gen :: Yes { .. } ) => this. make_gen_expr (
1279
+ CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1280
+ closure_id,
1281
+ None ,
1282
+ body. span ,
1283
+ hir:: CoroutineSource :: Fn ,
1284
+ mkbody,
1285
+ ) ,
1286
+ _ => unreachable ! ( "we must have either an async fn or a gen fn" ) ,
1287
+ } ;
1234
1288
1235
1289
let hir_id = this. lower_node_id ( closure_id) ;
1236
1290
this. maybe_forward_track_caller ( body. span , fn_id, hir_id) ;
1237
- let expr = hir:: Expr { hir_id, kind : async_expr , span : this. lower_span ( body. span ) } ;
1291
+ let expr = hir:: Expr { hir_id, kind : coroutine_expr , span : this. lower_span ( body. span ) } ;
1238
1292
1239
1293
( this. arena . alloc_from_iter ( parameters) , expr)
1240
1294
} )
@@ -1246,13 +1300,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
1246
1300
sig : & FnSig ,
1247
1301
id : NodeId ,
1248
1302
kind : FnDeclKind ,
1249
- is_async : Option < ( NodeId , Span ) > ,
1303
+ transform_return_type : Option < FnReturnTransformation > ,
1250
1304
) -> ( & ' hir hir:: Generics < ' hir > , hir:: FnSig < ' hir > ) {
1251
1305
let header = self . lower_fn_header ( sig. header ) ;
1252
1306
let itctx = ImplTraitContext :: Universal ;
1253
1307
let ( generics, decl) =
1254
1308
self . lower_generics ( generics, sig. header . constness , id, & itctx, |this| {
1255
- this. lower_fn_decl ( & sig. decl , id, sig. span , kind, is_async )
1309
+ this. lower_fn_decl ( & sig. decl , id, sig. span , kind, transform_return_type )
1256
1310
} ) ;
1257
1311
( generics, hir:: FnSig { header, decl, span : self . lower_span ( sig. span ) } )
1258
1312
}
0 commit comments