Skip to content

Commit 467f5e9

Browse files
committed
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.
2 parents 0406441 + 5b475a4 commit 467f5e9

File tree

5 files changed

+34
-17
lines changed

5 files changed

+34
-17
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ use rustc_span::Span;
1414
use tracing::debug;
1515

1616
macro_rules! gate_feature_fn {
17+
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
18+
let (visitor, has_feature, span, name, explain, help) =
19+
(&*$visitor, $has_feature, $span, $name, $explain, $help);
20+
let has_feature: bool = has_feature(visitor.features);
21+
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
22+
if !has_feature && !span.allows_unstable($name) {
23+
feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
24+
.help(help)
25+
.emit();
26+
}
27+
}};
1728
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
1829
let (visitor, has_feature, span, name, explain) =
1930
(&*$visitor, $has_feature, $span, $name, $explain);
@@ -27,6 +38,9 @@ macro_rules! gate_feature_fn {
2738
}
2839

2940
macro_rules! gate_feature_post {
41+
($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
42+
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
43+
};
3044
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
3145
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
3246
};
@@ -597,6 +611,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
597611

598612
let spans = sess.parse_sess.gated_spans.spans.borrow();
599613
macro_rules! gate_all {
614+
($gate:ident, $msg:literal, $help:literal) => {
615+
if let Some(spans) = spans.get(&sym::$gate) {
616+
for span in spans {
617+
gate_feature_post!(&visitor, $gate, *span, $msg, $help);
618+
}
619+
}
620+
};
600621
($gate:ident, $msg:literal) => {
601622
if let Some(spans) = spans.get(&sym::$gate) {
602623
for span in spans {
@@ -607,7 +628,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
607628
}
608629
gate_all!(if_let_guard, "`if let` guards are experimental");
609630
gate_all!(let_chains, "`let` expressions in this position are experimental");
610-
gate_all!(async_closure, "async closures are unstable");
631+
gate_all!(
632+
async_closure,
633+
"async closures are unstable",
634+
"to use an async block, remove the `||`: `async {`"
635+
);
611636
gate_all!(generators, "yield syntax is experimental");
612637
gate_all!(or_patterns, "or-patterns syntax is experimental");
613638
gate_all!(raw_ref_op, "raw address of syntax is experimental");

compiler/rustc_parse/src/parser/expr.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1599,10 +1599,6 @@ impl<'a> Parser<'a> {
15991599
} else {
16001600
Async::No
16011601
};
1602-
if let Async::Yes { span, .. } = asyncness {
1603-
// Feature-gate `async ||` closures.
1604-
self.sess.gated_spans.gate(sym::async_closure, span);
1605-
}
16061602

16071603
let capture_clause = self.parse_capture_clause()?;
16081604
let decl = self.parse_fn_block_decl()?;
@@ -1619,6 +1615,11 @@ impl<'a> Parser<'a> {
16191615
}
16201616
};
16211617

1618+
if let Async::Yes { span, .. } = asyncness {
1619+
// Feature-gate `async ||` closures.
1620+
self.sess.gated_spans.gate(sym::async_closure, span);
1621+
}
1622+
16221623
Ok(self.mk_expr(
16231624
lo.to(body.span),
16241625
ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),

src/test/ui/async-await/feature-async-closure.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | let _ = async || {};
66
|
77
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
88
= help: add `#![feature(async_closure)]` to the crate attributes to enable
9+
= help: to use an async block, remove the `||`: `async {`
910

1011
error: aborting due to previous error
1112

src/test/ui/parser/block-no-opening-brace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ fn f4() {
2626
}
2727

2828
fn f5() {
29-
async //~ ERROR async closures are unstable
29+
async
3030
let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
3131
}

src/test/ui/parser/block-no-opening-brace.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,5 @@ LL | async
3939
LL | let x = 0;
4040
| ^^^ unexpected token
4141

42-
error[E0658]: async closures are unstable
43-
--> $DIR/block-no-opening-brace.rs:29:5
44-
|
45-
LL | async
46-
| ^^^^^
47-
|
48-
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
49-
= help: add `#![feature(async_closure)]` to the crate attributes to enable
50-
51-
error: aborting due to 6 previous errors
42+
error: aborting due to 5 previous errors
5243

53-
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)