about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-07-05 13:53:06 +0200
committerGitHub <noreply@github.com>2019-07-05 13:53:06 +0200
commit84527e4676e21a574ff7d20d9680283cead0e828 (patch)
treebe98879e27deecd1be925499b8a272fececce666
parent61256a8164603f595fa29b29c3168b4514e2af5e (diff)
parent43315bc15e274d62b7bb239488066a21d40b4269 (diff)
downloadrust-84527e4676e21a574ff7d20d9680283cead0e828.tar.gz
rust-84527e4676e21a574ff7d20d9680283cead0e828.zip
Rollup merge of #62292 - Centril:split-async-closures, r=cramertj
Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: https://github.com/rust-lang/rust/issues/62290

Closes https://github.com/rust-lang/rust/issues/62214.

cc https://github.com/rust-lang/rust/issues/62149

r? @varkor
-rw-r--r--src/libsyntax/feature_gate.rs52
-rw-r--r--src/libsyntax/parse/lexer/mod.rs1
-rw-r--r--src/libsyntax/parse/mod.rs3
-rw-r--r--src/libsyntax/parse/parser.rs36
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/ui/async-await/async-await.rs8
-rw-r--r--src/test/ui/async-await/async-closure-matches-expr.rs12
-rw-r--r--src/test/ui/async-await/async-closure.rs81
-rw-r--r--src/test/ui/async-await/async-matches-expr.rs3
-rw-r--r--src/test/ui/async-await/await-macro.rs2
-rw-r--r--src/test/ui/async-await/feature-async-closure.rs8
-rw-r--r--src/test/ui/async-await/feature-async-closure.stderr12
-rw-r--r--src/test/ui/async-await/issues/issue-62009-1.rs (renamed from src/test/ui/async-await/issues/issue-62009.rs)2
-rw-r--r--src/test/ui/async-await/issues/issue-62009-1.stderr (renamed from src/test/ui/async-await/issues/issue-62009.stderr)23
-rw-r--r--src/test/ui/async-await/issues/issue-62009-2.rs10
-rw-r--r--src/test/ui/async-await/issues/issue-62009-2.stderr10
-rw-r--r--src/test/ui/async-await/no-args-non-move-async-closure.rs2
-rw-r--r--src/test/ui/async-await/suggest-missing-await-closure.fixed23
-rw-r--r--src/test/ui/async-await/suggest-missing-await-closure.rs23
-rw-r--r--src/test/ui/async-await/suggest-missing-await-closure.stderr15
-rw-r--r--src/test/ui/async-await/suggest-missing-await.fixed11
-rw-r--r--src/test/ui/async-await/suggest-missing-await.rs11
-rw-r--r--src/test/ui/async-await/suggest-missing-await.stderr14
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await.rs1
-rw-r--r--src/test/ui/feature-gates/feature-gate-async-await.stderr11
25 files changed, 260 insertions, 115 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 4a0c957333b..ab61f77f5cb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -31,6 +31,7 @@ use crate::tokenstream::TokenTree;
 
 use errors::{Applicability, DiagnosticBuilder, Handler};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lock;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::debug;
@@ -573,6 +574,9 @@ declare_features! (
     // Allows `impl Trait` with multiple unrelated lifetimes.
     (active, member_constraints, "1.37.0", Some(61977), None),
 
+    // Allows `async || body` closures.
+    (active, async_closure, "1.37.0", Some(62290), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -2191,9 +2195,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                     "labels on blocks are unstable");
                 }
             }
-            ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
-                gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
-            }
             ast::ExprKind::Async(..) => {
                 gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
             }
@@ -2527,6 +2528,10 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
     features
 }
 
+fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
+    vec.borrow().iter().for_each(f);
+}
+
 pub fn check_crate(krate: &ast::Crate,
                    sess: &ParseSess,
                    features: &Features,
@@ -2539,27 +2544,26 @@ pub fn check_crate(krate: &ast::Crate,
         plugin_attributes,
     };
 
-    sess
-        .param_attr_spans
-        .borrow()
-        .iter()
-        .for_each(|span| gate_feature!(
-            &ctx,
-            param_attrs,
-            *span,
-            "attributes on function parameters are unstable"
-        ));
-
-    sess
-        .let_chains_spans
-        .borrow()
-        .iter()
-        .for_each(|span| gate_feature!(
-            &ctx,
-            let_chains,
-            *span,
-            "`let` expressions in this position are experimental"
-        ));
+    for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
+        &ctx,
+        param_attrs,
+        *span,
+        "attributes on function parameters are unstable"
+    ));
+
+    for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
+        &ctx,
+        let_chains,
+        *span,
+        "`let` expressions in this position are experimental"
+    ));
+
+    for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
+        &ctx,
+        async_closure,
+        *span,
+        "async closures are unstable"
+    ));
 
     let visitor = &mut PostExpansionVisitor {
         context: &ctx,
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 49f714e4e46..3717bb435f6 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1452,6 +1452,7 @@ mod tests {
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
+            async_closure_spans: Lock::new(Vec::new()),
         }
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index e19eab371f4..4056905d5dd 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -57,6 +57,8 @@ pub struct ParseSess {
     pub param_attr_spans: Lock<Vec<Span>>,
     // Places where `let` exprs were used and should be feature gated according to `let_chains`.
     pub let_chains_spans: Lock<Vec<Span>>,
+    // Places where `async || ..` exprs were used and should be feature gated.
+    pub async_closure_spans: Lock<Vec<Span>>,
 }
 
 impl ParseSess {
@@ -84,6 +86,7 @@ impl ParseSess {
             ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
+            async_closure_spans: Lock::new(Vec::new()),
         }
     }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cef14632e64..a95b6891fb9 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3221,21 +3221,24 @@ impl<'a> Parser<'a> {
                              -> PResult<'a, P<Expr>>
     {
         let lo = self.token.span;
+
         let movability = if self.eat_keyword(kw::Static) {
             Movability::Static
         } else {
             Movability::Movable
         };
+
         let asyncness = if self.token.span.rust_2018() {
             self.parse_asyncness()
         } else {
             IsAsync::NotAsync
         };
-        let capture_clause = if self.eat_keyword(kw::Move) {
-            CaptureBy::Value
-        } else {
-            CaptureBy::Ref
-        };
+        if asyncness.is_async() {
+            // Feature gate `async ||` closures.
+            self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
+        }
+
+        let capture_clause = self.parse_capture_clause();
         let decl = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_span;
         let body = match decl.output {
@@ -3257,7 +3260,7 @@ impl<'a> Parser<'a> {
             attrs))
     }
 
-    // `else` token already eaten
+    /// `else` token already eaten
     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
         if self.eat_keyword(kw::If) {
             return self.parse_if_expr(ThinVec::new());
@@ -3306,7 +3309,7 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
     }
 
-    // parse `loop {...}`, `loop` token already eaten
+    /// Parse `loop {...}`, `loop` token already eaten.
     fn parse_loop_expr(&mut self, opt_label: Option<Label>,
                            span_lo: Span,
                            mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
@@ -3316,17 +3319,20 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
     }
 
-    /// Parses an `async move {...}` expression.
-    pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
-        -> PResult<'a, P<Expr>>
-    {
-        let span_lo = self.token.span;
-        self.expect_keyword(kw::Async)?;
-        let capture_clause = if self.eat_keyword(kw::Move) {
+    /// Parse an optional `move` prefix to a closure lke construct.
+    fn parse_capture_clause(&mut self) -> CaptureBy {
+        if self.eat_keyword(kw::Move) {
             CaptureBy::Value
         } else {
             CaptureBy::Ref
-        };
+        }
+    }
+
+    /// Parses an `async move? {...}` expression.
+    pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+        let span_lo = self.token.span;
+        self.expect_keyword(kw::Async)?;
+        let capture_clause = self.parse_capture_clause();
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         Ok(self.mk_expr(
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index aee988d5148..233574dda5d 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -146,6 +146,7 @@ symbols! {
         associated_type_defaults,
         associated_types,
         async_await,
+        async_closure,
         attr,
         attributes,
         attr_literals,
diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs
index 0eae1467fbf..29622c9d030 100644
--- a/src/test/ui/async-await/async-await.rs
+++ b/src/test/ui/async-await/async-await.rs
@@ -70,13 +70,6 @@ fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
     }
 }
 
-fn async_closure(x: u8) -> impl Future<Output = u8> {
-    (async move |x: u8| -> u8 {
-        wake_and_yield_once().await;
-        x
-    })(x)
-}
-
 async fn async_fn(x: u8) -> u8 {
     wake_and_yield_once().await;
     x
@@ -180,7 +173,6 @@ fn main() {
     test! {
         async_block,
         async_nonmove_block,
-        async_closure,
         async_fn,
         generic_async_fn,
         async_fn_with_internal_borrow,
diff --git a/src/test/ui/async-await/async-closure-matches-expr.rs b/src/test/ui/async-await/async-closure-matches-expr.rs
new file mode 100644
index 00000000000..90bd51ec5d0
--- /dev/null
+++ b/src/test/ui/async-await/async-closure-matches-expr.rs
@@ -0,0 +1,12 @@
+// compile-pass
+// edition:2018
+
+#![feature(async_await, async_closure)]
+
+macro_rules! match_expr {
+    ($x:expr) => {}
+}
+
+fn main() {
+    match_expr!(async || {});
+}
diff --git a/src/test/ui/async-await/async-closure.rs b/src/test/ui/async-await/async-closure.rs
new file mode 100644
index 00000000000..f5dc9e24d2d
--- /dev/null
+++ b/src/test/ui/async-await/async-closure.rs
@@ -0,0 +1,81 @@
+// run-pass
+
+// edition:2018
+// aux-build:arc_wake.rs
+
+#![feature(async_await, async_closure)]
+
+extern crate arc_wake;
+
+use std::pin::Pin;
+use std::future::Future;
+use std::sync::{
+    Arc,
+    atomic::{self, AtomicUsize},
+};
+use std::task::{Context, Poll};
+use arc_wake::ArcWake;
+
+struct Counter {
+    wakes: AtomicUsize,
+}
+
+impl ArcWake for Counter {
+    fn wake(self: Arc<Self>) {
+        Self::wake_by_ref(&self)
+    }
+    fn wake_by_ref(arc_self: &Arc<Self>) {
+        arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+    }
+}
+
+struct WakeOnceThenComplete(bool);
+
+fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
+
+impl Future for WakeOnceThenComplete {
+    type Output = ();
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+        if self.0 {
+            Poll::Ready(())
+        } else {
+            cx.waker().wake_by_ref();
+            self.0 = true;
+            Poll::Pending
+        }
+    }
+}
+
+fn async_closure(x: u8) -> impl Future<Output = u8> {
+    (async move |x: u8| -> u8 {
+        wake_and_yield_once().await;
+        x
+    })(x)
+}
+
+fn test_future_yields_once_then_returns<F, Fut>(f: F)
+where
+    F: FnOnce(u8) -> Fut,
+    Fut: Future<Output = u8>,
+{
+    let mut fut = Box::pin(f(9));
+    let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+    let waker = ArcWake::into_waker(counter.clone());
+    let mut cx = Context::from_waker(&waker);
+    assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
+    assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
+    assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
+    assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
+}
+
+fn main() {
+    macro_rules! test {
+        ($($fn_name:expr,)*) => { $(
+            test_future_yields_once_then_returns($fn_name);
+        )* }
+    }
+
+    test! {
+        async_closure,
+    }
+}
diff --git a/src/test/ui/async-await/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs
index e41a568ad29..a6f0211e41f 100644
--- a/src/test/ui/async-await/async-matches-expr.rs
+++ b/src/test/ui/async-await/async-matches-expr.rs
@@ -1,7 +1,7 @@
 // build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
-#![feature(async_await, await_macro)]
+#![feature(async_await)]
 
 macro_rules! match_expr {
     ($x:expr) => {}
@@ -9,5 +9,4 @@ macro_rules! match_expr {
 
 fn main() {
     match_expr!(async {});
-    match_expr!(async || {});
 }
diff --git a/src/test/ui/async-await/await-macro.rs b/src/test/ui/async-await/await-macro.rs
index 7d8b7a257da..c37835d73e9 100644
--- a/src/test/ui/async-await/await-macro.rs
+++ b/src/test/ui/async-await/await-macro.rs
@@ -3,7 +3,7 @@
 // edition:2018
 // aux-build:arc_wake.rs
 
-#![feature(async_await, await_macro)]
+#![feature(async_await, async_closure, await_macro)]
 
 extern crate arc_wake;
 
diff --git a/src/test/ui/async-await/feature-async-closure.rs b/src/test/ui/async-await/feature-async-closure.rs
new file mode 100644
index 00000000000..d07116b13a2
--- /dev/null
+++ b/src/test/ui/async-await/feature-async-closure.rs
@@ -0,0 +1,8 @@
+// edition:2018
+// gate-test-async_closure
+
+fn f() {
+    let _ = async || {}; //~ ERROR async closures are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/feature-async-closure.stderr b/src/test/ui/async-await/feature-async-closure.stderr
new file mode 100644
index 00000000000..61909f8659e
--- /dev/null
+++ b/src/test/ui/async-await/feature-async-closure.stderr
@@ -0,0 +1,12 @@
+error[E0658]: async closures are unstable
+  --> $DIR/feature-async-closure.rs:5:13
+   |
+LL |     let _ = async || {};
+   |             ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62290
+   = help: add #![feature(async_closure)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/async-await/issues/issue-62009.rs b/src/test/ui/async-await/issues/issue-62009-1.rs
index e2d58cac24d..ac6605bceff 100644
--- a/src/test/ui/async-await/issues/issue-62009.rs
+++ b/src/test/ui/async-await/issues/issue-62009-1.rs
@@ -11,8 +11,6 @@ fn main() {
     //~^ ERROR `await` is only allowed inside `async` functions and blocks
         let task1 = print_dur().await;
     }.await;
-    (async || 2333)().await;
-    //~^ ERROR `await` is only allowed inside `async` functions and blocks
     (|_| 2333).await;
     //~^ ERROR `await` is only allowed inside `async` functions and blocks
     //~^^ ERROR
diff --git a/src/test/ui/async-await/issues/issue-62009.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr
index 53d1f34fe4f..2bbb6d079ea 100644
--- a/src/test/ui/async-await/issues/issue-62009.stderr
+++ b/src/test/ui/async-await/issues/issue-62009-1.stderr
@@ -1,5 +1,5 @@
 error[E0728]: `await` is only allowed inside `async` functions and blocks
-  --> $DIR/issue-62009.rs:8:5
+  --> $DIR/issue-62009-1.rs:8:5
    |
 LL | fn main() {
    |    ---- this is not `async`
@@ -7,7 +7,7 @@ LL |     async { let (); }.await;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
 
 error[E0728]: `await` is only allowed inside `async` functions and blocks
-  --> $DIR/issue-62009.rs:10:5
+  --> $DIR/issue-62009-1.rs:10:5
    |
 LL |   fn main() {
    |      ---- this is not `async`
@@ -19,16 +19,7 @@ LL | |     }.await;
    | |___________^ only allowed inside `async` functions and blocks
 
 error[E0728]: `await` is only allowed inside `async` functions and blocks
-  --> $DIR/issue-62009.rs:14:5
-   |
-LL | fn main() {
-   |    ---- this is not `async`
-...
-LL |     (async || 2333)().await;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
-
-error[E0728]: `await` is only allowed inside `async` functions and blocks
-  --> $DIR/issue-62009.rs:16:5
+  --> $DIR/issue-62009-1.rs:14:5
    |
 LL | fn main() {
    |    ---- this is not `async`
@@ -36,14 +27,14 @@ LL | fn main() {
 LL |     (|_| 2333).await;
    |     ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
 
-error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
-  --> $DIR/issue-62009.rs:16:5
+error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std::future::Future` is not satisfied
+  --> $DIR/issue-62009-1.rs:14:5
    |
 LL |     (|_| 2333).await;
-   |     ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
+   |     ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]`
    |
    = note: required by `std::future::poll_with_tls_context`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issues/issue-62009-2.rs b/src/test/ui/async-await/issues/issue-62009-2.rs
new file mode 100644
index 00000000000..52b62eaa9e0
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-62009-2.rs
@@ -0,0 +1,10 @@
+// edition:2018
+
+#![feature(async_await, async_closure)]
+
+async fn print_dur() {}
+
+fn main() {
+    (async || 2333)().await;
+    //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr
new file mode 100644
index 00000000000..79b6803263e
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-62009-2.stderr
@@ -0,0 +1,10 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+  --> $DIR/issue-62009-2.rs:8:5
+   |
+LL | fn main() {
+   |    ---- this is not `async`
+LL |     (async || 2333)().await;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs
index 345f19b0623..0615f290692 100644
--- a/src/test/ui/async-await/no-args-non-move-async-closure.rs
+++ b/src/test/ui/async-await/no-args-non-move-async-closure.rs
@@ -1,6 +1,6 @@
 // edition:2018
 
-#![feature(async_await, await_macro)]
+#![feature(async_await, async_closure, await_macro)]
 
 fn main() {
     let _ = async |x: u8| {};
diff --git a/src/test/ui/async-await/suggest-missing-await-closure.fixed b/src/test/ui/async-await/suggest-missing-await-closure.fixed
new file mode 100644
index 00000000000..60c9a8581ac
--- /dev/null
+++ b/src/test/ui/async-await/suggest-missing-await-closure.fixed
@@ -0,0 +1,23 @@
+// edition:2018
+// run-rustfix
+
+#![feature(async_await, async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+    22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+    async || {
+        let x = make_u32();
+        take_u32(x.await)
+        //~^ ERROR mismatched types [E0308]
+        //~| HELP consider using `.await` here
+        //~| SUGGESTION x.await
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await-closure.rs b/src/test/ui/async-await/suggest-missing-await-closure.rs
new file mode 100644
index 00000000000..cb992a27bc1
--- /dev/null
+++ b/src/test/ui/async-await/suggest-missing-await-closure.rs
@@ -0,0 +1,23 @@
+// edition:2018
+// run-rustfix
+
+#![feature(async_await, async_closure)]
+
+fn take_u32(_x: u32) {}
+
+async fn make_u32() -> u32 {
+    22
+}
+
+#[allow(unused)]
+async fn suggest_await_in_async_closure() {
+    async || {
+        let x = make_u32();
+        take_u32(x)
+        //~^ ERROR mismatched types [E0308]
+        //~| HELP consider using `.await` here
+        //~| SUGGESTION x.await
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr
new file mode 100644
index 00000000000..487ca6c0fc5
--- /dev/null
+++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-missing-await-closure.rs:16:18
+   |
+LL |         take_u32(x)
+   |                  ^
+   |                  |
+   |                  expected u32, found opaque type
+   |                  help: consider using `.await` here: `x.await`
+   |
+   = note: expected type `u32`
+              found type `impl std::future::Future`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed
index 282be368c69..aa032682be8 100644
--- a/src/test/ui/async-await/suggest-missing-await.fixed
+++ b/src/test/ui/async-await/suggest-missing-await.fixed
@@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() {
     //~| SUGGESTION x.await
 }
 
-#[allow(unused)]
-async fn suggest_await_in_async_closure() {
-    async || {
-        let x = make_u32();
-        take_u32(x.await)
-        //~^ ERROR mismatched types [E0308]
-        //~| HELP consider using `.await` here
-        //~| SUGGESTION x.await
-    };
-}
-
 fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index 36103f050c1..2ca814fbb22 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() {
     //~| SUGGESTION x.await
 }
 
-#[allow(unused)]
-async fn suggest_await_in_async_closure() {
-    async || {
-        let x = make_u32();
-        take_u32(x)
-        //~^ ERROR mismatched types [E0308]
-        //~| HELP consider using `.await` here
-        //~| SUGGESTION x.await
-    };
-}
-
 fn main() {}
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 59c20dcfbc9..9bae7150276 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -10,18 +10,6 @@ LL |     take_u32(x)
    = note: expected type `u32`
               found type `impl std::future::Future`
 
-error[E0308]: mismatched types
-  --> $DIR/suggest-missing-await.rs:25:18
-   |
-LL |         take_u32(x)
-   |                  ^
-   |                  |
-   |                  expected u32, found opaque type
-   |                  help: consider using `.await` here: `x.await`
-   |
-   = note: expected type `u32`
-              found type `impl std::future::Future`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs
index 9cfefef4129..78391c0e104 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await.rs
+++ b/src/test/ui/feature-gates/feature-gate-async-await.rs
@@ -15,5 +15,4 @@ async fn foo() {} //~ ERROR async fn is unstable
 
 fn main() {
     let _ = async {}; //~ ERROR async blocks are unstable
-    let _ = async || {}; //~ ERROR async closures are unstable
 }
diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr
index 43e41b45458..1ea4da8da0c 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr
@@ -40,15 +40,6 @@ LL |     let _ = async {};
    = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(async_await)] to the crate attributes to enable
 
-error[E0658]: async closures are unstable
-  --> $DIR/feature-gate-async-await.rs:18:13
-   |
-LL |     let _ = async || {};
-   |             ^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/50547
-   = help: add #![feature(async_await)] to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0658`.