about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl4
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs39
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs29
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0708.md6
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.rs3
-rw-r--r--tests/ui/async-await/async-borrowck-escaping-closure-error.stderr21
-rw-r--r--tests/ui/async-await/no-params-non-move-async-closure.rs2
-rw-r--r--tests/ui/async-await/no-params-non-move-async-closure.stderr11
-rw-r--r--tests/ui/suggestions/suggest-on-bare-closure-call.stderr5
10 files changed, 40 insertions, 88 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index e7177402db1..8615016cda5 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses =
 ast_lowering_async_coroutines_not_supported =
     `async` coroutines are not yet supported
 
-ast_lowering_async_non_move_closure_not_supported =
-    `async` non-`move` closures with parameters are not currently supported
-    .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
-
 ast_lowering_att_syntax_only_x86 =
     the `att_syntax` option is only supported on x86
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 2811fe104cd..4843d36372d 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -146,14 +146,6 @@ pub struct ClosureCannotBeStatic {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[help]
-#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
-pub struct AsyncNonMoveClosureNotSupported {
-    #[primary_span]
-    pub fn_decl_span: Span,
-}
-
-#[derive(Diagnostic, Clone, Copy)]
 #[diag(ast_lowering_functional_record_update_destructuring_assignment)]
 pub struct FunctionalRecordUpdateDestructuringAssignment {
     #[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index e0b1a10c82e..0920de48eb8 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,6 +1,6 @@
 use super::errors::{
-    AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
-    BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
+    AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
+    ClosureCannotBeStatic, CoroutineTooManyParameters,
     FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
     NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
     UnderscoreExprLhsAssign,
@@ -13,7 +13,6 @@ use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_middle::span_bug;
 use rustc_session::errors::report_lit_error;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1028,28 +1027,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         fn_decl_span: Span,
         fn_arg_span: Span,
     ) -> hir::ExprKind<'hir> {
-        let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else {
-            span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet");
-        };
-
         if let &ClosureBinder::For { span, .. } = binder {
             self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
         }
 
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
-        let outer_decl =
-            FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
-
         let body = self.with_new_scopes(fn_decl_span, |this| {
-            // FIXME(cramertj): allow `async` non-`move` closures with arguments.
-            if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
-                this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
-            }
-
             // Transform `async |x: u8| -> X { ... }` into
             // `|x: u8| || -> X { ... }`.
-            let body_id = this.lower_fn_body(&outer_decl, |this| {
+            let body_id = this.lower_body(|this| {
                 let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
                     let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
                     Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
@@ -1057,22 +1044,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     None
                 };
 
-                let async_body = this.make_desugared_coroutine_expr(
-                    capture_clause,
-                    inner_closure_id,
-                    async_ret_ty,
+                let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
+                    decl,
+                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
                     body.span,
-                    hir::CoroutineDesugaring::Async,
+                    coroutine_kind,
                     hir::CoroutineSource::Closure,
-                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
+                    async_ret_ty,
                 );
-                let hir_id = this.lower_node_id(inner_closure_id);
+
+                let hir_id = this.lower_node_id(coroutine_kind.closure_id());
                 this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
-                hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) }
+
+                (parameters, expr)
             });
             body_id
         });
 
+        let outer_decl =
+            FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
+
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
         // 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
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c8e639b7a96..dd3f7289a60 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1085,9 +1085,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.lower_body(|this| {
             let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
                 decl,
-                body,
+                |this| this.lower_block_expr(body),
+                body.span,
                 coroutine_kind,
-                CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
+                hir::CoroutineSource::Fn,
+                None,
             );
 
             // FIXME(async_fn_track_caller): Can this be moved above?
@@ -1102,12 +1104,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// into the body. This is to make sure that the future actually owns the
     /// arguments that are passed to the function, and to ensure things like
     /// drop order are stable.
-    fn lower_coroutine_body_with_moved_arguments(
+    pub fn lower_coroutine_body_with_moved_arguments(
         &mut self,
         decl: &FnDecl,
-        body: &Block,
+        lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
+        body_span: Span,
         coroutine_kind: CoroutineKind,
-        capture_clause: CaptureBy,
+        coroutine_source: hir::CoroutineSource,
+        return_type_hint: Option<hir::FnRetTy<'hir>>,
     ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
         let mut parameters: Vec<hir::Param<'_>> = Vec::new();
         let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
@@ -1246,7 +1250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
             // Create a block from the user's function body:
-            let user_body = this.lower_block_expr(body);
+            let user_body = lower_body(this);
 
             // Transform into `drop-temps { <user-body> }`, an expression:
             let desugared_span =
@@ -1277,19 +1281,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let closure_id = coroutine_kind.closure_id();
         let coroutine_expr = self.make_desugared_coroutine_expr(
-            capture_clause,
+            // FIXME(async_closures): This should only move locals,
+            // and not upvars. Capturing closure upvars by ref doesn't
+            // work right now anyways, so whatever.
+            CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
             closure_id,
-            None,
-            body.span,
+            return_type_hint,
+            body_span,
             desugaring_kind,
-            hir::CoroutineSource::Fn,
+            coroutine_source,
             mkbody,
         );
 
         let expr = hir::Expr {
             hir_id: self.lower_node_id(closure_id),
             kind: coroutine_expr,
-            span: self.lower_span(body.span),
+            span: self.lower_span(body_span),
         };
 
         (self.arena.alloc_from_iter(parameters), expr)
diff --git a/compiler/rustc_error_codes/src/error_codes/E0708.md b/compiler/rustc_error_codes/src/error_codes/E0708.md
index 9287fc803d1..61a853ac446 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0708.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0708.md
@@ -1,12 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `async` non-`move` closures with parameters are currently not supported.
 
 Erroneous code example:
 
-```compile_fail,edition2018,E0708
+```edition2018
 #![feature(async_closure)]
 
 fn main() {
-    let add_one = async |num: u8| { // error!
+    let add_one = async |num: u8| {
         num + 1
     };
 }
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
index e667b72aee5..f8ff9186842 100644
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
+++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs
@@ -1,9 +1,10 @@
 // edition:2018
+// check-pass
+
 #![feature(async_closure)]
 fn foo() -> Box<dyn std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new((async || x)())
-    //~^ ERROR E0373
 }
 
 fn main() {
diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
deleted file mode 100644
index 1d8d1c67bae..00000000000
--- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-closure-error.rs:5:15
-   |
-LL |     Box::new((async || x)())
-   |               ^^^^^^^^ - `x` is borrowed here
-   |               |
-   |               may outlive borrowed value `x`
-   |
-note: closure is returned here
-  --> $DIR/async-borrowck-escaping-closure-error.rs:5:5
-   |
-LL |     Box::new((async || x)())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
-   |
-LL |     Box::new((async move || x)())
-   |                     ++++
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs
index 3b15f35c260..1440d918c50 100644
--- a/tests/ui/async-await/no-params-non-move-async-closure.rs
+++ b/tests/ui/async-await/no-params-non-move-async-closure.rs
@@ -1,8 +1,8 @@
 // edition:2018
+// check-pass
 
 #![feature(async_closure)]
 
 fn main() {
     let _ = async |x: u8| {};
-    //~^ ERROR `async` non-`move` closures with parameters are not currently supported
 }
diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr
deleted file mode 100644
index d2659553699..00000000000
--- a/tests/ui/async-await/no-params-non-move-async-closure.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0708]: `async` non-`move` closures with parameters are not currently supported
-  --> $DIR/no-params-non-move-async-closure.rs:6:13
-   |
-LL |     let _ = async |x: u8| {};
-   |             ^^^^^^^^^^^^^
-   |
-   = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0708`.
diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
index e65a6eb4939..77631b36e0f 100644
--- a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
+++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr
@@ -18,11 +18,6 @@ LL |     let _ = async ||{}();
    |                     ^^--
    |                     |
    |                     call expression requires function
-   |
-help: if you meant to create this closure and immediately call it, surround the closure with parentheses
-   |
-LL |     let _ = (async ||{})();
-   |             +          +
 
 error: aborting due to 2 previous errors