about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2025-02-11 11:13:33 -0300
committerSantiago Pastorino <spastorino@gmail.com>2025-03-06 17:58:33 -0300
commit292aa8704957f0c0a94cc0cb01c74267d2bdfe27 (patch)
tree1d249de7f8adee2b9bd7dd81f797ba92e9cee636
parent7c17bf8e824aefcc4272168f1cbda21c1683dcbe (diff)
downloadrust-292aa8704957f0c0a94cc0cb01c74267d2bdfe27.tar.gz
rust-292aa8704957f0c0a94cc0cb01c74267d2bdfe27.zip
Fix use closure parsing error message
-rw-r--r--compiler/rustc_parse/src/parser/item.rs19
-rw-r--r--tests/ui/ergonomic-clones/closure/parse.rs4
-rw-r--r--tests/ui/ergonomic-clones/closure/parse.stderr12
3 files changed, 20 insertions, 15 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 961e81989d6..678376aee4f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -209,9 +209,7 @@ impl<'a> Parser<'a> {
         let check_pub = def == &Defaultness::Final;
         let mut def_ = || mem::replace(def, Defaultness::Final);
 
-        let info = if !self.look_ahead(1, |t| [token::OrOr, token::Or].contains(&t.kind))
-            && self.eat_keyword_case(exp!(Use), case)
-        {
+        let info = if !self.is_use_closure() && self.eat_keyword_case(exp!(Use), case) {
             self.parse_use_item()?
         } else if self.check_fn_front_matter(check_pub, case) {
             // FUNCTION ITEM
@@ -1279,6 +1277,21 @@ impl<'a> Parser<'a> {
         None
     }
 
+    fn is_use_closure(&self) -> bool {
+        if self.token.is_keyword(kw::Use) {
+            // Check if this could be a closure.
+            self.look_ahead(1, |token| {
+                // Move or Async here would be an error but still we're parsing a closure
+                let dist =
+                    if token.is_keyword(kw::Move) || token.is_keyword(kw::Async) { 2 } else { 1 };
+
+                self.look_ahead(dist, |token| matches!(token.kind, token::Or | token::OrOr))
+            })
+        } else {
+            false
+        }
+    }
+
     fn is_unsafe_foreign_mod(&self) -> bool {
         self.token.is_keyword(kw::Unsafe)
             && self.is_keyword_ahead(1, &[kw::Extern])
diff --git a/tests/ui/ergonomic-clones/closure/parse.rs b/tests/ui/ergonomic-clones/closure/parse.rs
index d4523de57ff..23fce20e370 100644
--- a/tests/ui/ergonomic-clones/closure/parse.rs
+++ b/tests/ui/ergonomic-clones/closure/parse.rs
@@ -14,9 +14,7 @@ fn parse2() {
 
 fn parse3() {
     use move || {
-        //~^ ERROR expected identifier, found keyword `move`
-        //~| ERROR expected one of `::`, `;`, or `as`, found `||`
-        // FIXME ideally we should error like in the previous example
+        //~^ ERROR expected one of `async`, `|`, or `||`, found keyword `move`
     };
 }
 
diff --git a/tests/ui/ergonomic-clones/closure/parse.stderr b/tests/ui/ergonomic-clones/closure/parse.stderr
index ac86a041929..c45c46eefa5 100644
--- a/tests/ui/ergonomic-clones/closure/parse.stderr
+++ b/tests/ui/ergonomic-clones/closure/parse.stderr
@@ -18,17 +18,11 @@ error: expected one of `async`, `|`, or `||`, found keyword `use`
 LL |     move use || {
    |          ^^^ expected one of `async`, `|`, or `||`
 
-error: expected identifier, found keyword `move`
+error: expected one of `async`, `|`, or `||`, found keyword `move`
   --> $DIR/parse.rs:16:9
    |
 LL |     use move || {
-   |         ^^^^ expected identifier, found keyword
+   |         ^^^^ expected one of `async`, `|`, or `||`
 
-error: expected one of `::`, `;`, or `as`, found `||`
-  --> $DIR/parse.rs:16:14
-   |
-LL |     use move || {
-   |              ^^ expected one of `::`, `;`, or `as`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors