about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/lowering/expr.rs116
1 files changed, 67 insertions, 49 deletions
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index 6ae39d192c3..01eca00a913 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -268,55 +268,13 @@ impl LoweringContext<'_> {
                 capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
             ) => {
                 if let IsAsync::Async { closure_id, .. } = asyncness {
-                    let outer_decl = FnDecl {
-                        inputs: decl.inputs.clone(),
-                        output: FunctionRetTy::Default(fn_decl_span),
-                        c_variadic: false,
-                    };
-                    // We need to lower the declaration outside the new scope, because we
-                    // have to conserve the state of being inside a loop condition for the
-                    // closure argument types.
-                    let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
-
-                    self.with_new_scopes(|this| {
-                        // FIXME(cramertj): allow `async` non-`move` closures with arguments.
-                        if capture_clause == CaptureBy::Ref &&
-                            !decl.inputs.is_empty()
-                        {
-                            struct_span_err!(
-                                this.sess,
-                                fn_decl_span,
-                                E0708,
-                                "`async` non-`move` closures with arguments \
-                                are not currently supported",
-                            )
-                                .help("consider using `let` statements to manually capture \
-                                       variables by reference before entering an \
-                                       `async move` closure")
-                                .emit();
-                        }
-
-                        // Transform `async |x: u8| -> X { ... }` into
-                        // `|x: u8| future_from_generator(|| -> X { ... })`.
-                        let body_id = this.lower_fn_body(&outer_decl, |this| {
-                            let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
-                                Some(ty.clone())
-                            } else { None };
-                            let async_body = this.make_async_expr(
-                                capture_clause, closure_id, async_ret_ty, body.span,
-                                |this| {
-                                    this.with_new_scopes(|this| this.lower_expr(body))
-                                });
-                            this.expr(fn_decl_span, async_body, ThinVec::new())
-                        });
-                        hir::ExprKind::Closure(
-                            this.lower_capture_clause(capture_clause),
-                            fn_decl,
-                            body_id,
-                            fn_decl_span,
-                            None,
-                        )
-                    })
+                    self.lower_expr_async_closure(
+                        capture_clause,
+                        closure_id,
+                        decl,
+                        body,
+                        fn_decl_span,
+                    )
                 } else {
                     // Lower outside new scope to preserve `is_in_loop_condition`.
                     let fn_decl = self.lower_fn_decl(decl, None, false, None);
@@ -449,6 +407,66 @@ impl LoweringContext<'_> {
         }
     }
 
+    fn lower_expr_async_closure(
+        &mut self,
+        capture_clause: CaptureBy,
+        closure_id: NodeId,
+        decl: &FnDecl,
+        body: &Expr,
+        fn_decl_span: Span,
+    ) -> hir::ExprKind {
+        let outer_decl = FnDecl {
+            inputs: decl.inputs.clone(),
+            output: FunctionRetTy::Default(fn_decl_span),
+            c_variadic: false,
+        };
+        // We need to lower the declaration outside the new scope, because we
+        // have to conserve the state of being inside a loop condition for the
+        // closure argument types.
+        let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
+
+        self.with_new_scopes(|this| {
+            // FIXME(cramertj): allow `async` non-`move` closures with arguments.
+            if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
+                struct_span_err!(
+                    this.sess,
+                    fn_decl_span,
+                    E0708,
+                    "`async` non-`move` closures with arguments are not currently supported",
+                )
+                .help(
+                    "consider using `let` statements to manually capture \
+                    variables by reference before entering an `async move` closure"
+                )
+                .emit();
+            }
+
+            // Transform `async |x: u8| -> X { ... }` into
+            // `|x: u8| future_from_generator(|| -> X { ... })`.
+            let body_id = this.lower_fn_body(&outer_decl, |this| {
+                let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
+                    Some(ty.clone())
+                } else {
+                    None
+                };
+                let async_body = this.make_async_expr(
+                    capture_clause, closure_id, async_ret_ty, body.span,
+                    |this| {
+                        this.with_new_scopes(|this| this.lower_expr(body))
+                    }
+                );
+                this.expr(fn_decl_span, async_body, ThinVec::new())
+            });
+            hir::ExprKind::Closure(
+                this.lower_capture_clause(capture_clause),
+                fn_decl,
+                body_id,
+                fn_decl_span,
+                None,
+            )
+        })
+    }
+
     /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind {
         let id = self.next_id();