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 } ;
@@ -208,13 +210,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
208
210
// only cares about the input argument patterns in the function
209
211
// declaration (decl), not the return types.
210
212
let asyncness = header. asyncness ;
211
- let body_id =
212
- this. lower_maybe_async_body ( span, hir_id, decl, asyncness, body. as_deref ( ) ) ;
213
+ let genness = header. genness ;
214
+ let body_id = this. lower_maybe_coroutine_body (
215
+ span,
216
+ hir_id,
217
+ decl,
218
+ asyncness,
219
+ genness,
220
+ body. as_deref ( ) ,
221
+ ) ;
213
222
214
223
let itctx = ImplTraitContext :: Universal ;
215
224
let ( generics, decl) =
216
225
this. lower_generics ( generics, header. constness , id, & itctx, |this| {
217
- let ret_id = asyncness. opt_return_id ( ) ;
226
+ let ret_id = asyncness
227
+ . opt_return_id ( )
228
+ . map ( |( node_id, span) | {
229
+ crate :: FnReturnTransformation :: Async ( node_id, span)
230
+ } )
231
+ . or_else ( || match genness {
232
+ Gen :: Yes { span, closure_id : _, return_impl_trait_id } => {
233
+ Some ( crate :: FnReturnTransformation :: Iterator (
234
+ return_impl_trait_id,
235
+ span,
236
+ ) )
237
+ }
238
+ _ => None ,
239
+ } ) ;
218
240
this. lower_fn_decl ( decl, id, * fn_sig_span, FnDeclKind :: Fn , ret_id)
219
241
} ) ;
220
242
let sig = hir:: FnSig {
@@ -733,20 +755,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
733
755
sig,
734
756
i. id ,
735
757
FnDeclKind :: Trait ,
736
- asyncness. opt_return_id ( ) ,
758
+ asyncness
759
+ . opt_return_id ( )
760
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
737
761
) ;
738
762
( generics, hir:: TraitItemKind :: Fn ( sig, hir:: TraitFn :: Required ( names) ) , false )
739
763
}
740
764
AssocItemKind :: Fn ( box Fn { sig, generics, body : Some ( body) , .. } ) => {
741
765
let asyncness = sig. header . asyncness ;
742
- let body_id =
743
- self . lower_maybe_async_body ( i. span , hir_id, & sig. decl , asyncness, Some ( body) ) ;
766
+ let genness = sig. header . genness ;
767
+ let body_id = self . lower_maybe_coroutine_body (
768
+ i. span ,
769
+ hir_id,
770
+ & sig. decl ,
771
+ asyncness,
772
+ genness,
773
+ Some ( body) ,
774
+ ) ;
744
775
let ( generics, sig) = self . lower_method_sig (
745
776
generics,
746
777
sig,
747
778
i. id ,
748
779
FnDeclKind :: Trait ,
749
- asyncness. opt_return_id ( ) ,
780
+ asyncness
781
+ . opt_return_id ( )
782
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
750
783
) ;
751
784
( generics, hir:: TraitItemKind :: Fn ( sig, hir:: TraitFn :: Provided ( body_id) ) , true )
752
785
}
@@ -836,19 +869,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
836
869
) ,
837
870
AssocItemKind :: Fn ( box Fn { sig, generics, body, .. } ) => {
838
871
let asyncness = sig. header . asyncness ;
839
- let body_id = self . lower_maybe_async_body (
872
+ let genness = sig. header . genness ;
873
+ let body_id = self . lower_maybe_coroutine_body (
840
874
i. span ,
841
875
hir_id,
842
876
& sig. decl ,
843
877
asyncness,
878
+ genness,
844
879
body. as_deref ( ) ,
845
880
) ;
846
881
let ( generics, sig) = self . lower_method_sig (
847
882
generics,
848
883
sig,
849
884
i. id ,
850
885
if self . is_in_trait_impl { FnDeclKind :: Impl } else { FnDeclKind :: Inherent } ,
851
- asyncness. opt_return_id ( ) ,
886
+ asyncness
887
+ . opt_return_id ( )
888
+ . map ( |( node_id, span) | crate :: FnReturnTransformation :: Async ( node_id, span) ) ,
852
889
) ;
853
890
854
891
( generics, hir:: ImplItemKind :: Fn ( sig, body_id) )
@@ -1012,16 +1049,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
1012
1049
} )
1013
1050
}
1014
1051
1015
- fn lower_maybe_async_body (
1052
+ /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or
1053
+ /// `gen {}` block as appropriate.
1054
+ fn lower_maybe_coroutine_body (
1016
1055
& mut self ,
1017
1056
span : Span ,
1018
1057
fn_id : hir:: HirId ,
1019
1058
decl : & FnDecl ,
1020
1059
asyncness : Async ,
1060
+ genness : Gen ,
1021
1061
body : Option < & Block > ,
1022
1062
) -> hir:: BodyId {
1023
- let ( closure_id, body) = match ( asyncness, body) {
1024
- ( Async :: Yes { closure_id, .. } , Some ( body) ) => ( closure_id, body) ,
1063
+ let ( closure_id, body) = match ( asyncness, genness, body) {
1064
+ // FIXME(eholk): do something reasonable for `async gen fn`. Probably that's an error
1065
+ // for now since it's not supported.
1066
+ ( Async :: Yes { closure_id, .. } , _, Some ( body) )
1067
+ | ( _, Gen :: Yes { closure_id, .. } , Some ( body) ) => ( closure_id, body) ,
1025
1068
_ => return self . lower_fn_body_block ( span, decl, body) ,
1026
1069
} ;
1027
1070
@@ -1164,44 +1207,55 @@ impl<'hir> LoweringContext<'_, 'hir> {
1164
1207
parameters. push ( new_parameter) ;
1165
1208
}
1166
1209
1167
- let async_expr = this. make_async_expr (
1168
- CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1169
- closure_id,
1170
- None ,
1171
- body. span ,
1172
- hir:: CoroutineSource :: Fn ,
1173
- |this| {
1174
- // Create a block from the user's function body:
1175
- let user_body = this. lower_block_expr ( body) ;
1210
+ let mkbody = |this : & mut LoweringContext < ' _ , ' hir > | {
1211
+ // Create a block from the user's function body:
1212
+ let user_body = this. lower_block_expr ( body) ;
1176
1213
1177
- // Transform into `drop-temps { <user-body> }`, an expression:
1178
- let desugared_span =
1179
- this. mark_span_with_reason ( DesugaringKind :: Async , user_body. span , None ) ;
1180
- let user_body =
1181
- this. expr_drop_temps ( desugared_span, this. arena . alloc ( user_body) ) ;
1214
+ // Transform into `drop-temps { <user-body> }`, an expression:
1215
+ let desugared_span =
1216
+ this. mark_span_with_reason ( DesugaringKind :: Async , user_body. span , None ) ;
1217
+ let user_body = this. expr_drop_temps ( desugared_span, this. arena . alloc ( user_body) ) ;
1182
1218
1183
- // As noted above, create the final block like
1184
- //
1185
- // ```
1186
- // {
1187
- // let $param_pattern = $raw_param;
1188
- // ...
1189
- // drop-temps { <user-body> }
1190
- // }
1191
- // ```
1192
- let body = this. block_all (
1193
- desugared_span,
1194
- this. arena . alloc_from_iter ( statements) ,
1195
- Some ( user_body) ,
1196
- ) ;
1219
+ // As noted above, create the final block like
1220
+ //
1221
+ // ```
1222
+ // {
1223
+ // let $param_pattern = $raw_param;
1224
+ // ...
1225
+ // drop-temps { <user-body> }
1226
+ // }
1227
+ // ```
1228
+ let body = this. block_all (
1229
+ desugared_span,
1230
+ this. arena . alloc_from_iter ( statements) ,
1231
+ Some ( user_body) ,
1232
+ ) ;
1197
1233
1198
- this. expr_block ( body)
1199
- } ,
1200
- ) ;
1234
+ this. expr_block ( body)
1235
+ } ;
1236
+ let coroutine_expr = match ( asyncness, genness) {
1237
+ ( Async :: Yes { .. } , _) => this. make_async_expr (
1238
+ CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1239
+ closure_id,
1240
+ None ,
1241
+ body. span ,
1242
+ hir:: CoroutineSource :: Fn ,
1243
+ mkbody,
1244
+ ) ,
1245
+ ( _, Gen :: Yes { .. } ) => this. make_gen_expr (
1246
+ CaptureBy :: Value { move_kw : rustc_span:: DUMMY_SP } ,
1247
+ closure_id,
1248
+ None ,
1249
+ body. span ,
1250
+ hir:: CoroutineSource :: Fn ,
1251
+ mkbody,
1252
+ ) ,
1253
+ _ => unreachable ! ( "we must have either an async fn or a gen fn" ) ,
1254
+ } ;
1201
1255
1202
1256
let hir_id = this. lower_node_id ( closure_id) ;
1203
1257
this. maybe_forward_track_caller ( body. span , fn_id, hir_id) ;
1204
- let expr = hir:: Expr { hir_id, kind : async_expr , span : this. lower_span ( body. span ) } ;
1258
+ let expr = hir:: Expr { hir_id, kind : coroutine_expr , span : this. lower_span ( body. span ) } ;
1205
1259
1206
1260
( this. arena . alloc_from_iter ( parameters) , expr)
1207
1261
} )
@@ -1213,13 +1267,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
1213
1267
sig : & FnSig ,
1214
1268
id : NodeId ,
1215
1269
kind : FnDeclKind ,
1216
- is_async : Option < ( NodeId , Span ) > ,
1270
+ transform_return_type : Option < FnReturnTransformation > ,
1217
1271
) -> ( & ' hir hir:: Generics < ' hir > , hir:: FnSig < ' hir > ) {
1218
1272
let header = self . lower_fn_header ( sig. header ) ;
1219
1273
let itctx = ImplTraitContext :: Universal ;
1220
1274
let ( generics, decl) =
1221
1275
self . lower_generics ( generics, sig. header . constness , id, & itctx, |this| {
1222
- this. lower_fn_decl ( & sig. decl , id, sig. span , kind, is_async )
1276
+ this. lower_fn_decl ( & sig. decl , id, sig. span , kind, transform_return_type )
1223
1277
} ) ;
1224
1278
( generics, hir:: FnSig { header, decl, span : self . lower_span ( sig. span ) } )
1225
1279
}
0 commit comments