Skip to content

Commit 299c2fc

Browse files
authored
Rollup merge of #80160 - diondokter:move_async_fix, r=davidtwco
Implemented a compiler diagnostic for move async mistake Fixes #79694 First time contributing, so I hope I'm doing everything right. (If not, please correct me!) This code performs a check when a move capture clause is parsed. The check is to detect if the user has reversed the async move keywords and to provide a diagnostic with a suggestion to fix it. Checked code: ```rust fn main() { move async { }; } ``` Previous output: ```txt PS C:\Repos\move_async_test> cargo build Compiling move_async_test v0.1.0 (C:\Repos\move_async_test) error: expected one of `|` or `||`, found keyword `async` --> src\main.rs:2:10 | 2 | move async { }; | ^^^^^ expected one of `|` or `||` error: aborting due to previous error error: could not compile `move_async_test` ``` New output: ```txt PS C:\Repos\move_async_test> cargo +dev build Compiling move_async_test v0.1.0 (C:\Repos\move_async_test) error: the order of `move` and `async` is incorrect --> src\main.rs:2:13 | 2 | let _ = move async { }; | ^^^^^^^^^^ | help: try switching the order | 2 | let _ = async move { }; | ^^^^^^^^^^ error: aborting due to previous error error: could not compile `move_async_test` ``` Is there a file/module where these kind of things are tested? Would love some feedback 😄
2 parents 787b016 + a272d62 commit 299c2fc

File tree

5 files changed

+61
-4
lines changed

5 files changed

+61
-4
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1912,4 +1912,22 @@ impl<'a> Parser<'a> {
19121912
*self = snapshot;
19131913
Err(err)
19141914
}
1915+
1916+
/// Get the diagnostics for the cases where `move async` is found.
1917+
///
1918+
/// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
1919+
pub(super) fn incorrect_move_async_order_found(
1920+
&self,
1921+
move_async_span: Span,
1922+
) -> DiagnosticBuilder<'a> {
1923+
let mut err =
1924+
self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
1925+
err.span_suggestion_verbose(
1926+
move_async_span,
1927+
"try switching the order",
1928+
"async move".to_owned(),
1929+
Applicability::MaybeIncorrect,
1930+
);
1931+
err
1932+
}
19151933
}

compiler/rustc_parse/src/parser/expr.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,7 @@ impl<'a> Parser<'a> {
16031603
self.sess.gated_spans.gate(sym::async_closure, span);
16041604
}
16051605

1606-
let capture_clause = self.parse_capture_clause();
1606+
let capture_clause = self.parse_capture_clause()?;
16071607
let decl = self.parse_fn_block_decl()?;
16081608
let decl_hi = self.prev_token.span;
16091609
let body = match decl.output {
@@ -1626,8 +1626,18 @@ impl<'a> Parser<'a> {
16261626
}
16271627

16281628
/// Parses an optional `move` prefix to a closure-like construct.
1629-
fn parse_capture_clause(&mut self) -> CaptureBy {
1630-
if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref }
1629+
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
1630+
if self.eat_keyword(kw::Move) {
1631+
// Check for `move async` and recover
1632+
if self.check_keyword(kw::Async) {
1633+
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
1634+
Err(self.incorrect_move_async_order_found(move_async_span))
1635+
} else {
1636+
Ok(CaptureBy::Value)
1637+
}
1638+
} else {
1639+
Ok(CaptureBy::Ref)
1640+
}
16311641
}
16321642

16331643
/// Parses the `|arg, arg|` header of a closure.
@@ -2019,7 +2029,7 @@ impl<'a> Parser<'a> {
20192029
fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
20202030
let lo = self.token.span;
20212031
self.expect_keyword(kw::Async)?;
2022-
let capture_clause = self.parse_capture_clause();
2032+
let capture_clause = self.parse_capture_clause()?;
20232033
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
20242034
attrs.extend(iattrs);
20252035
let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
// edition:2018
3+
4+
// Regression test for issue 79694
5+
6+
fn main() {
7+
let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-rustfix
2+
// edition:2018
3+
4+
// Regression test for issue 79694
5+
6+
fn main() {
7+
let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: the order of `move` and `async` is incorrect
2+
--> $DIR/incorrect-move-async-order-issue-79694.rs:7:13
3+
|
4+
LL | let _ = move async { };
5+
| ^^^^^^^^^^
6+
|
7+
help: try switching the order
8+
|
9+
LL | let _ = async move { };
10+
| ^^^^^^^^^^
11+
12+
error: aborting due to previous error
13+

0 commit comments

Comments
 (0)