@@ -268,55 +268,13 @@ impl LoweringContext<'_> {
268
268
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
269
269
) => {
270
270
if let IsAsync :: Async { closure_id, .. } = asyncness {
271
- let outer_decl = FnDecl {
272
- inputs : decl. inputs . clone ( ) ,
273
- output : FunctionRetTy :: Default ( fn_decl_span) ,
274
- c_variadic : false ,
275
- } ;
276
- // We need to lower the declaration outside the new scope, because we
277
- // have to conserve the state of being inside a loop condition for the
278
- // closure argument types.
279
- let fn_decl = self . lower_fn_decl ( & outer_decl, None , false , None ) ;
280
-
281
- self . with_new_scopes ( |this| {
282
- // FIXME(cramertj): allow `async` non-`move` closures with arguments.
283
- if capture_clause == CaptureBy :: Ref &&
284
- !decl. inputs . is_empty ( )
285
- {
286
- struct_span_err ! (
287
- this. sess,
288
- fn_decl_span,
289
- E0708 ,
290
- "`async` non-`move` closures with arguments \
291
- are not currently supported",
292
- )
293
- . help ( "consider using `let` statements to manually capture \
294
- variables by reference before entering an \
295
- `async move` closure")
296
- . emit ( ) ;
297
- }
298
-
299
- // Transform `async |x: u8| -> X { ... }` into
300
- // `|x: u8| future_from_generator(|| -> X { ... })`.
301
- let body_id = this. lower_fn_body ( & outer_decl, |this| {
302
- let async_ret_ty = if let FunctionRetTy :: Ty ( ty) = & decl. output {
303
- Some ( ty. clone ( ) )
304
- } else { None } ;
305
- let async_body = this. make_async_expr (
306
- capture_clause, closure_id, async_ret_ty, body. span ,
307
- |this| {
308
- this. with_new_scopes ( |this| this. lower_expr ( body) )
309
- } ) ;
310
- this. expr ( fn_decl_span, async_body, ThinVec :: new ( ) )
311
- } ) ;
312
- hir:: ExprKind :: Closure (
313
- this. lower_capture_clause ( capture_clause) ,
314
- fn_decl,
315
- body_id,
316
- fn_decl_span,
317
- None ,
318
- )
319
- } )
271
+ self . lower_expr_async_closure (
272
+ capture_clause,
273
+ closure_id,
274
+ decl,
275
+ body,
276
+ fn_decl_span,
277
+ )
320
278
} else {
321
279
// Lower outside new scope to preserve `is_in_loop_condition`.
322
280
let fn_decl = self . lower_fn_decl ( decl, None , false , None ) ;
@@ -449,6 +407,66 @@ impl LoweringContext<'_> {
449
407
}
450
408
}
451
409
410
+ fn lower_expr_async_closure (
411
+ & mut self ,
412
+ capture_clause : CaptureBy ,
413
+ closure_id : NodeId ,
414
+ decl : & FnDecl ,
415
+ body : & Expr ,
416
+ fn_decl_span : Span ,
417
+ ) -> hir:: ExprKind {
418
+ let outer_decl = FnDecl {
419
+ inputs : decl. inputs . clone ( ) ,
420
+ output : FunctionRetTy :: Default ( fn_decl_span) ,
421
+ c_variadic : false ,
422
+ } ;
423
+ // We need to lower the declaration outside the new scope, because we
424
+ // have to conserve the state of being inside a loop condition for the
425
+ // closure argument types.
426
+ let fn_decl = self . lower_fn_decl ( & outer_decl, None , false , None ) ;
427
+
428
+ self . with_new_scopes ( |this| {
429
+ // FIXME(cramertj): allow `async` non-`move` closures with arguments.
430
+ if capture_clause == CaptureBy :: Ref && !decl. inputs . is_empty ( ) {
431
+ struct_span_err ! (
432
+ this. sess,
433
+ fn_decl_span,
434
+ E0708 ,
435
+ "`async` non-`move` closures with arguments are not currently supported" ,
436
+ )
437
+ . help (
438
+ "consider using `let` statements to manually capture \
439
+ variables by reference before entering an `async move` closure"
440
+ )
441
+ . emit ( ) ;
442
+ }
443
+
444
+ // Transform `async |x: u8| -> X { ... }` into
445
+ // `|x: u8| future_from_generator(|| -> X { ... })`.
446
+ let body_id = this. lower_fn_body ( & outer_decl, |this| {
447
+ let async_ret_ty = if let FunctionRetTy :: Ty ( ty) = & decl. output {
448
+ Some ( ty. clone ( ) )
449
+ } else {
450
+ None
451
+ } ;
452
+ let async_body = this. make_async_expr (
453
+ capture_clause, closure_id, async_ret_ty, body. span ,
454
+ |this| {
455
+ this. with_new_scopes ( |this| this. lower_expr ( body) )
456
+ }
457
+ ) ;
458
+ this. expr ( fn_decl_span, async_body, ThinVec :: new ( ) )
459
+ } ) ;
460
+ hir:: ExprKind :: Closure (
461
+ this. lower_capture_clause ( capture_clause) ,
462
+ fn_decl,
463
+ body_id,
464
+ fn_decl_span,
465
+ None ,
466
+ )
467
+ } )
468
+ }
469
+
452
470
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
453
471
fn lower_expr_range_closed ( & mut self , span : Span , e1 : & Expr , e2 : & Expr ) -> hir:: ExprKind {
454
472
let id = self . next_id ( ) ;
0 commit comments