@@ -268,55 +268,13 @@ impl LoweringContext<'_> {
268268 capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
269269 ) => {
270270 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+ )
320278 } else {
321279 // Lower outside new scope to preserve `is_in_loop_condition`.
322280 let fn_decl = self . lower_fn_decl ( decl, None , false , None ) ;
@@ -449,6 +407,66 @@ impl LoweringContext<'_> {
449407 }
450408 }
451409
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+
452470 /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
453471 fn lower_expr_range_closed ( & mut self , span : Span , e1 : & Expr , e2 : & Expr ) -> hir:: ExprKind {
454472 let id = self . next_id ( ) ;
0 commit comments