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