about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-12 02:56:51 +0000
committerbors <bors@rust-lang.org>2021-01-12 02:56:51 +0000
commit467f5e99a541db94235f0c173bdffc8aeb177522 (patch)
tree49044dd7f4359e27a047f8bb6c3349dcc2e86e59
parent04064416644eba7351b1a457c1de27d28a750c95 (diff)
parent5b475a46181cc4e8bfe2ac64f3724a5c485d6c5c (diff)
downloadrust-467f5e99a541db94235f0c173bdffc8aeb177522.tar.gz
rust-467f5e99a541db94235f0c173bdffc8aeb177522.zip
Auto merge of #76580 - rokob:iss76011, r=estebank
Suggest async {} for async || {}

Fixes #76011

This adds support for adding help diagnostics to the feature gating checks and
then uses it for the async_closure gate to add the extra bit of help
information as described in the issue.
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs27
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs9
-rw-r--r--src/test/ui/async-await/feature-async-closure.stderr1
-rw-r--r--src/test/ui/parser/block-no-opening-brace.rs2
-rw-r--r--src/test/ui/parser/block-no-opening-brace.stderr12
5 files changed, 34 insertions, 17 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 435f32535b6..d65bc820f8f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -14,6 +14,17 @@ use rustc_span::Span;
 use tracing::debug;
 
 macro_rules! gate_feature_fn {
+    ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
+        let (visitor, has_feature, span, name, explain, help) =
+            (&*$visitor, $has_feature, $span, $name, $explain, $help);
+        let has_feature: bool = has_feature(visitor.features);
+        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
+        if !has_feature && !span.allows_unstable($name) {
+            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
+                .help(help)
+                .emit();
+        }
+    }};
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
         let (visitor, has_feature, span, name, explain) =
             (&*$visitor, $has_feature, $span, $name, $explain);
@@ -27,6 +38,9 @@ macro_rules! gate_feature_fn {
 }
 
 macro_rules! gate_feature_post {
+    ($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
+        gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
+    };
     ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
         gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
@@ -597,6 +611,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 
     let spans = sess.parse_sess.gated_spans.spans.borrow();
     macro_rules! gate_all {
+        ($gate:ident, $msg:literal, $help:literal) => {
+            if let Some(spans) = spans.get(&sym::$gate) {
+                for span in spans {
+                    gate_feature_post!(&visitor, $gate, *span, $msg, $help);
+                }
+            }
+        };
         ($gate:ident, $msg:literal) => {
             if let Some(spans) = spans.get(&sym::$gate) {
                 for span in spans {
@@ -607,7 +628,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     }
     gate_all!(if_let_guard, "`if let` guards are experimental");
     gate_all!(let_chains, "`let` expressions in this position are experimental");
-    gate_all!(async_closure, "async closures are unstable");
+    gate_all!(
+        async_closure,
+        "async closures are unstable",
+        "to use an async block, remove the `||`: `async {`"
+    );
     gate_all!(generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index d11db74a3bd..f4332e4548a 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1599,10 +1599,6 @@ impl<'a> Parser<'a> {
         } else {
             Async::No
         };
-        if let Async::Yes { span, .. } = asyncness {
-            // Feature-gate `async ||` closures.
-            self.sess.gated_spans.gate(sym::async_closure, span);
-        }
 
         let capture_clause = self.parse_capture_clause()?;
         let decl = self.parse_fn_block_decl()?;
@@ -1619,6 +1615,11 @@ impl<'a> Parser<'a> {
             }
         };
 
+        if let Async::Yes { span, .. } = asyncness {
+            // Feature-gate `async ||` closures.
+            self.sess.gated_spans.gate(sym::async_closure, span);
+        }
+
         Ok(self.mk_expr(
             lo.to(body.span),
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
diff --git a/src/test/ui/async-await/feature-async-closure.stderr b/src/test/ui/async-await/feature-async-closure.stderr
index ba851ba7d29..485a838b67f 100644
--- a/src/test/ui/async-await/feature-async-closure.stderr
+++ b/src/test/ui/async-await/feature-async-closure.stderr
@@ -6,6 +6,7 @@ LL |     let _ = async || {};
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
    = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: to use an async block, remove the `||`: `async {`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs
index e4bb39f6836..8a6599488b1 100644
--- a/src/test/ui/parser/block-no-opening-brace.rs
+++ b/src/test/ui/parser/block-no-opening-brace.rs
@@ -26,6 +26,6 @@ fn f4() {
     }
 
 fn f5() {
-    async //~ ERROR async closures are unstable
+    async
         let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
     }
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
index a88e4ac44cf..e32c8bdc73a 100644
--- a/src/test/ui/parser/block-no-opening-brace.stderr
+++ b/src/test/ui/parser/block-no-opening-brace.stderr
@@ -39,15 +39,5 @@ LL |     async
 LL |         let x = 0;
    |         ^^^ unexpected token
 
-error[E0658]: async closures are unstable
-  --> $DIR/block-no-opening-brace.rs:29:5
-   |
-LL |     async
-   |     ^^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` 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`.