about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-12-06 05:53:44 +0100
committerLukas Wirth <lukastw97@gmail.com>2024-12-06 05:57:00 +0100
commit3db9b1d943f7a665ea98a6dab40ece33375f4f99 (patch)
tree3aebd3d945bb072318234a181c1c94780e37fb83
parent6ef7f8e01409884d160769d6a62ba3d82dfb0207 (diff)
downloadrust-3db9b1d943f7a665ea98a6dab40ece33375f4f99.tar.gz
rust-3db9b1d943f7a665ea98a6dab40ece33375f4f99.zip
fix: Fix parser getting stuck for bad asm expressions
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs18
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast50
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs5
4 files changed, 71 insertions, 4 deletions
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index cd2ce59f627..407320e1d08 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -345,10 +345,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
             name(p);
             p.bump(T![=]);
             allow_templates = false;
-            true
-        } else {
-            false
-        };
+        }
 
         let op = p.start();
         let dir_spec = p.start();
@@ -399,6 +396,19 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
             op.abandon(p);
             op_n.abandon(p);
             p.err_and_bump("expected asm operand");
+
+            // improves error recovery and handles err_and_bump recovering from `{` which gets
+            // the parser stuck here
+            if p.at(T!['{']) {
+                // test_err bad_asm_expr
+                // fn foo() {
+                //     builtin#asm(
+                //         label crashy = { return; }
+                //     );
+                // }
+                expr(p);
+            }
+
             if p.at(T!['}']) {
                 break;
             }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
index f9486f53c25..c4ffc6cadc8 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -704,6 +704,8 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/async_without_semicolon.rs");
     }
     #[test]
+    fn bad_asm_expr() { run_and_expect_errors("test_data/parser/inline/err/bad_asm_expr.rs"); }
+    #[test]
     fn comma_after_functional_update_syntax() {
         run_and_expect_errors(
             "test_data/parser/inline/err/comma_after_functional_update_syntax.rs",
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast
new file mode 100644
index 00000000000..306446e64dd
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rast
@@ -0,0 +1,50 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        EXPR_STMT
+          ASM_EXPR
+            BUILTIN_KW "builtin"
+            POUND "#"
+            ASM_KW "asm"
+            L_PAREN "("
+            WHITESPACE "\n        "
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "label"
+            WHITESPACE " "
+            NAME
+              IDENT "crashy"
+            WHITESPACE " "
+            EQ "="
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE " "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                  SEMICOLON ";"
+                WHITESPACE " "
+                R_CURLY "}"
+            WHITESPACE "\n    "
+            R_PAREN ")"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 41: expected COMMA
+error 50: expected asm operand
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs
new file mode 100644
index 00000000000..6056f925e33
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/bad_asm_expr.rs
@@ -0,0 +1,5 @@
+fn foo() {
+    builtin#asm(
+        label crashy = { return; }
+    );
+}