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.
This commit is contained in:
parent
25b2f48612
commit
5b475a4618
5 changed files with 34 additions and 17 deletions
|
@ -14,6 +14,17 @@ use rustc_span::Span;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
macro_rules! gate_feature_fn {
|
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) => {{
|
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||||
let (visitor, has_feature, span, name, explain) =
|
let (visitor, has_feature, span, name, explain) =
|
||||||
(&*$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 {
|
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) => {
|
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
||||||
};
|
};
|
||||||
|
@ -613,6 +627,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||||
|
|
||||||
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
||||||
macro_rules! gate_all {
|
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) => {
|
($gate:ident, $msg:literal) => {
|
||||||
if let Some(spans) = spans.get(&sym::$gate) {
|
if let Some(spans) = spans.get(&sym::$gate) {
|
||||||
for span in spans {
|
for span in spans {
|
||||||
|
@ -623,7 +644,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||||
}
|
}
|
||||||
gate_all!(if_let_guard, "`if let` guard is not implemented");
|
gate_all!(if_let_guard, "`if let` guard is not implemented");
|
||||||
gate_all!(let_chains, "`let` expressions in this position 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!(generators, "yield syntax is experimental");
|
||||||
gate_all!(or_patterns, "or-patterns syntax is experimental");
|
gate_all!(or_patterns, "or-patterns syntax is experimental");
|
||||||
gate_all!(raw_ref_op, "raw address of syntax is experimental");
|
gate_all!(raw_ref_op, "raw address of syntax is experimental");
|
||||||
|
|
|
@ -1554,10 +1554,6 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
Async::No
|
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 capture_clause = self.parse_capture_clause();
|
||||||
let decl = self.parse_fn_block_decl()?;
|
let decl = self.parse_fn_block_decl()?;
|
||||||
|
@ -1574,6 +1570,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(
|
Ok(self.mk_expr(
|
||||||
lo.to(body.span),
|
lo.to(body.span),
|
||||||
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
|
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
|
||||||
|
|
|
@ -6,6 +6,7 @@ LL | let _ = async || {};
|
||||||
|
|
|
|
||||||
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
|
= 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: 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,6 @@ fn f4() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f5() {
|
fn f5() {
|
||||||
async //~ ERROR async closures are unstable
|
async
|
||||||
let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
|
let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,15 +39,5 @@ LL | async
|
||||||
LL | let x = 0;
|
LL | let x = 0;
|
||||||
| ^^^ unexpected token
|
| ^^^ unexpected token
|
||||||
|
|
||||||
error[E0658]: async closures are unstable
|
error: aborting due to 5 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue