Skip to content

Commit ba00a23

Browse files
authored
Rollup merge of rust-lang#80160 - diondokter:move_async_fix, r=davidtwco
Implemented a compiler diagnostic for move async mistake Fixes rust-lang#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 2f2741b + a272d62 commit ba00a23

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
@@ -1604,7 +1604,7 @@ impl<'a> Parser<'a> {
16041604
self.sess.gated_spans.gate(sym::async_closure, span);
16051605
}
16061606

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

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

16341644
/// Parses the `|arg, arg|` header of a closure.
@@ -2020,7 +2030,7 @@ impl<'a> Parser<'a> {
20202030
fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
20212031
let lo = self.token.span;
20222032
self.expect_keyword(kw::Async)?;
2023-
let capture_clause = self.parse_capture_clause();
2033+
let capture_clause = self.parse_capture_clause()?;
20242034
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
20252035
attrs.extend(iattrs);
20262036
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)