about summary refs log tree commit diff
diff options
context:
space:
mode:
authorXFFXFF <1247714429@qq.com>2023-03-04 09:58:59 +0800
committerXFFXFF <1247714429@qq.com>2023-03-07 08:24:25 +0800
commit995aacfce8b16472aa21cf0a030aebedfe7ed2bc (patch)
treedff838eff728438e3d303c741921415c414e7578
parent31c12ec282de5e2d4e835f320f8858277b3ba133 (diff)
downloadrust-995aacfce8b16472aa21cf0a030aebedfe7ed2bc.tar.gz
rust-995aacfce8b16472aa21cf0a030aebedfe7ed2bc.zip
show diagnostic for } token followed by else in let else statement
-rw-r--r--crates/parser/src/grammar/attributes.rs2
-rw-r--r--crates/parser/src/grammar/expressions.rs33
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs4
-rw-r--r--crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast69
-rw-r--r--crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs1
5 files changed, 101 insertions, 8 deletions
diff --git a/crates/parser/src/grammar/attributes.rs b/crates/parser/src/grammar/attributes.rs
index 4ecaa6e6a85..c13a1943792 100644
--- a/crates/parser/src/grammar/attributes.rs
+++ b/crates/parser/src/grammar/attributes.rs
@@ -43,7 +43,7 @@ pub(super) fn meta(p: &mut Parser<'_>) {
     match p.current() {
         T![=] => {
             p.bump(T![=]);
-            if !expressions::expr(p) {
+            if expressions::expr(p).is_none() {
                 p.error("expected expression");
             }
         }
diff --git a/crates/parser/src/grammar/expressions.rs b/crates/parser/src/grammar/expressions.rs
index 4b080102a2c..7232cdfef06 100644
--- a/crates/parser/src/grammar/expressions.rs
+++ b/crates/parser/src/grammar/expressions.rs
@@ -16,9 +16,9 @@ pub(super) enum Semicolon {
 
 const EXPR_FIRST: TokenSet = LHS_FIRST;
 
-pub(super) fn expr(p: &mut Parser<'_>) -> bool {
+pub(super) fn expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
     let r = Restrictions { forbid_structs: false, prefer_stmt: false };
-    expr_bp(p, None, r, 1).is_some()
+    expr_bp(p, None, r, 1).map(|(m, _)| m)
 }
 
 pub(super) fn expr_stmt(
@@ -120,16 +120,32 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
             // fn f() { let x: i32; }
             types::ascription(p);
         }
+
+        let mut is_block_like_expr_after_eq = false;
         if p.eat(T![=]) {
             // test let_stmt_init
             // fn f() { let x = 92; }
-            expressions::expr(p);
+            let expr = expressions::expr(p);
+
+            if let Some(expr) = expr {
+                is_block_like_expr_after_eq = match expr.kind() {
+                    IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
+                    _ => false,
+                };
+            }
         }
 
         if p.at(T![else]) {
+            // test_err let_else_right_curly_brace
+            // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
+            if is_block_like_expr_after_eq {
+                p.error(
+                    "right curly brace `}` before `else` in a `let...else` statement not allowed",
+                )
+            }
+
             // test let_else
             // fn f() { let Some(x) = opt else { return }; }
-
             let m = p.start();
             p.bump(T![else]);
             block_expr(p);
@@ -578,7 +594,14 @@ fn arg_list(p: &mut Parser<'_>) {
     // fn main() {
     //     foo(#[attr] 92)
     // }
-    delimited(p, T!['('], T![')'], T![,], EXPR_FIRST.union(ATTRIBUTE_FIRST), expr);
+    delimited(
+        p,
+        T!['('],
+        T![')'],
+        T![,],
+        EXPR_FIRST.union(ATTRIBUTE_FIRST),
+        |p: &mut Parser<'_>| expr(p).is_some(),
+    );
     m.complete(p, ARG_LIST);
 }
 
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index efc2603835e..a33a1d2543e 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -188,7 +188,7 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
 
         // test tuple_attrs
         // const A: (i64, i64) = (1, #[cfg(test)] 2);
-        if !expr(p) {
+        if expr(p).is_none() {
             break;
         }
 
@@ -221,7 +221,7 @@ fn array_expr(p: &mut Parser<'_>) -> CompletedMarker {
 
         // test array_attrs
         // const A: &[i64] = &[1, #[cfg(test)] 2];
-        if !expr(p) {
+        if expr(p).is_none() {
             break;
         }
 
diff --git a/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast b/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast
new file mode 100644
index 00000000000..6ec580212b4
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast
@@ -0,0 +1,69 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "func"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE " "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          TUPLE_STRUCT_PAT
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "Some"
+            L_PAREN "("
+            WILDCARD_PAT
+              UNDERSCORE "_"
+            R_PAREN ")"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          BLOCK_EXPR
+            STMT_LIST
+              L_CURLY "{"
+              CALL_EXPR
+                PATH_EXPR
+                  PATH
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "Some"
+                ARG_LIST
+                  L_PAREN "("
+                  LITERAL
+                    INT_NUMBER "1"
+                  R_PAREN ")"
+              R_CURLY "}"
+          WHITESPACE " "
+          LET_ELSE
+            ELSE_KW "else"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE " "
+                MACRO_EXPR
+                  MACRO_CALL
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "panic"
+                    BANG "!"
+                    TOKEN_TREE
+                      L_PAREN "("
+                      STRING "\"h\""
+                      R_PAREN ")"
+                WHITESPACE " "
+                R_CURLY "}"
+          SEMICOLON ";"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 35: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs b/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs
new file mode 100644
index 00000000000..30d52fea3b2
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs
@@ -0,0 +1 @@
+fn func() { let Some(_) = {Some(1)} else { panic!("h") };}