about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <me@lukaswirth.dev>2025-06-11 14:03:57 +0200
committerLukas Wirth <me@lukaswirth.dev>2025-06-11 17:11:58 +0200
commitedc405d383b896c0417ad1ba33558cf1c506af48 (patch)
tree3c03735f0e65cb319c9f5b288c304e36b9a465e8
parent2b0274c71dba0e24370ebf65593da450e2e91868 (diff)
downloadrust-edc405d383b896c0417ad1ba33558cf1c506af48.tar.gz
rust-edc405d383b896c0417ad1ba33558cf1c506af48.zip
Add expectation for `{` when parsing lone coroutine qualifiers
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs32
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.stderr8
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.stderr16
-rw-r--r--tests/ui/parser/block-no-opening-brace.rs4
-rw-r--r--tests/ui/parser/block-no-opening-brace.stderr6
-rw-r--r--tests/ui/parser/misspelled-keywords/async-move.stderr4
6 files changed, 38 insertions, 32 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a298c4d4dec..93489aa8ee9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1520,22 +1520,20 @@ impl<'a> Parser<'a> {
                 Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
             } else if this.token_uninterpolated_span().at_least_rust_2018() {
                 // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
+                let at_async = this.check_keyword(exp!(Async));
+                // check for `gen {}` and `gen move {}`
+                // or `async gen {}` and `async gen move {}`
+                // FIXME: (async) gen closures aren't yet parsed.
+                // FIXME(gen_blocks): Parse `gen async` and suggest swap
                 if this.token_uninterpolated_span().at_least_rust_2024()
-                    // check for `gen {}` and `gen move {}`
-                    // or `async gen {}` and `async gen move {}`
-                    && (this.is_gen_block(kw::Gen, 0)
-                        || (this.check_keyword(exp!(Async)) && this.is_gen_block(kw::Gen, 1)))
+                    && this.is_gen_block(kw::Gen, at_async as usize)
                 {
-                    // FIXME: (async) gen closures aren't yet parsed.
                     this.parse_gen_block()
-                } else if this.check_keyword(exp!(Async)) {
-                    // FIXME(gen_blocks): Parse `gen async` and suggest swap
-                    if this.is_gen_block(kw::Async, 0) {
-                        // Check for `async {` and `async move {`,
-                        this.parse_gen_block()
-                    } else {
-                        this.parse_expr_closure()
-                    }
+                // Check for `async {` and `async move {`,
+                } else if this.is_gen_block(kw::Async, 0) {
+                    this.parse_gen_block()
+                } else if at_async {
+                    this.parse_expr_closure()
                 } else if this.eat_keyword_noexpect(kw::Await) {
                     this.recover_incorrect_await_syntax(lo)
                 } else {
@@ -2407,6 +2405,14 @@ impl<'a> Parser<'a> {
             None
         };
 
+        if let ClosureBinder::NotPresent = binder
+            && coroutine_kind.is_some()
+        {
+            // coroutine closures and generators can have the same qualifiers, so we might end up
+            // in here if there is a missing `|` but also no `{`. Adjust the expectations in that case.
+            self.expected_token_types.insert(TokenType::OpenBrace);
+        }
+
         let capture_clause = self.parse_capture_clause()?;
         let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_token.span;
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
index 152a6f3a41e..34f5c7d3084 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -44,22 +44,22 @@ note: while trying to match `r#async`
 LL |     (r#async) => (1)
    |      ^^^^^^^
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23
    |
 LL |     ($i: ident) => ($i)
-   |                       ^ expected one of `move`, `use`, `|`, or `||`
+   |                       ^ expected one of `move`, `use`, `{`, `|`, or `||`
    |
   ::: $DIR/edition-keywords-2018-2015-parsing.rs:22:8
    |
 LL |     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
    |        -------------------- in this macro invocation
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/edition-keywords-2018-2015-parsing.rs:24:24
    |
 LL |     if passes_tt!(async) == 1 {}
-   |                        ^ expected one of `move`, `use`, `|`, or `||`
+   |                        ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
 error[E0308]: mismatched types
   --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
index 53f1b827f9c..dd3f4938c74 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -44,34 +44,34 @@ note: while trying to match `r#async`
 LL |     (r#async) => (1)
    |      ^^^^^^^
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23
    |
 LL |     ($i: ident) => ($i)
-   |                       ^ expected one of `move`, `use`, `|`, or `||`
+   |                       ^ expected one of `move`, `use`, `{`, `|`, or `||`
    |
   ::: $DIR/edition-keywords-2018-2018-parsing.rs:29:8
    |
 LL |     if passes_ident!(async) == 1 {} // FIXME: Edition hygiene bug, async here is 2018 and reserved
    |        -------------------- in this macro invocation
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:31:24
    |
 LL |     if passes_tt!(async) == 1 {}
-   |                        ^ expected one of `move`, `use`, `|`, or `||`
+   |                        ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:14:23
    |
 LL |     ($i: ident) => ($i)
-   |                       ^ expected one of `move`, `use`, `|`, or `||`
+   |                       ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
-error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `|`, or `||`
+error: macro expansion ends with an incomplete expression: expected one of `move`, `use`, `{`, `|`, or `||`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:35:30
    |
 LL |     if local_passes_tt!(async) == 1 {}
-   |                              ^ expected one of `move`, `use`, `|`, or `||`
+   |                              ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
 error[E0308]: mismatched types
   --> $DIR/edition-keywords-2018-2018-parsing.rs:40:33
diff --git a/tests/ui/parser/block-no-opening-brace.rs b/tests/ui/parser/block-no-opening-brace.rs
index b08c830bfc7..ea5a98ff6fc 100644
--- a/tests/ui/parser/block-no-opening-brace.rs
+++ b/tests/ui/parser/block-no-opening-brace.rs
@@ -27,10 +27,10 @@ fn in_try() {
         let x = 0;
 }
 
-// FIXME(#80931)
 fn in_async() {
     async
-        let x = 0; //~ ERROR expected one of `move`, `use`, `|`, or `||`, found keyword `let`
+        let x = 0;
+    //~^ ERROR expected one of `move`, `use`, `{`, `|`, or `||`, found keyword `let`
 }
 
 // FIXME(#78168)
diff --git a/tests/ui/parser/block-no-opening-brace.stderr b/tests/ui/parser/block-no-opening-brace.stderr
index f51ee92626f..cf9eeba573d 100644
--- a/tests/ui/parser/block-no-opening-brace.stderr
+++ b/tests/ui/parser/block-no-opening-brace.stderr
@@ -43,11 +43,11 @@ error: expected expression, found reserved keyword `try`
 LL |     try
    |     ^^^ expected expression
 
-error: expected one of `move`, `use`, `|`, or `||`, found keyword `let`
-  --> $DIR/block-no-opening-brace.rs:33:9
+error: expected one of `move`, `use`, `{`, `|`, or `||`, found keyword `let`
+  --> $DIR/block-no-opening-brace.rs:32:9
    |
 LL |     async
-   |          - expected one of `move`, `use`, `|`, or `||`
+   |          - expected one of `move`, `use`, `{`, `|`, or `||`
 LL |         let x = 0;
    |         ^^^ unexpected token
 
diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr
index 2507326fb28..26449a17f78 100644
--- a/tests/ui/parser/misspelled-keywords/async-move.stderr
+++ b/tests/ui/parser/misspelled-keywords/async-move.stderr
@@ -1,8 +1,8 @@
-error: expected one of `move`, `use`, `|`, or `||`, found `Move`
+error: expected one of `move`, `use`, `{`, `|`, or `||`, found `Move`
   --> $DIR/async-move.rs:4:11
    |
 LL |     async Move {}
-   |           ^^^^ expected one of `move`, `use`, `|`, or `||`
+   |           ^^^^ expected one of `move`, `use`, `{`, `|`, or `||`
    |
 help: write keyword `move` in lowercase
    |