about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-01-17 13:29:56 +0000
committerGitHub <noreply@github.com>2025-01-17 13:29:56 +0000
commitff5c32f5424b439e7c510a74feb1d7d4f01ab6ae (patch)
treea4d8172f6c0a36bf7727298d4e6425a02a7bcae7
parent99c701307094b6bad58b8df796fa00de0fe0935b (diff)
parent474c73bd946c029573e989115c660d518e53c8ee (diff)
downloadrust-ff5c32f5424b439e7c510a74feb1d7d4f01ab6ae.tar.gz
rust-ff5c32f5424b439e7c510a74feb1d7d4f01ab6ae.zip
Merge pull request #18908 from jnyfah/error-braces
Fix: Detect missing errors for } braces before else in let...else statements
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/event.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs10
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/parser.rs25
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast79
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs8
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast42
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast90
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast40
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast55
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast38
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast90
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs7
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast40
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast38
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast45
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs5
23 files changed, 637 insertions, 12 deletions
diff --git a/src/tools/rust-analyzer/crates/parser/src/event.rs b/src/tools/rust-analyzer/crates/parser/src/event.rs
index e38571dd3ec..b197b086f37 100644
--- a/src/tools/rust-analyzer/crates/parser/src/event.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/event.rs
@@ -12,7 +12,7 @@ use crate::{
 /// `Parser` produces a flat list of `Event`s.
 /// They are converted to a tree-structure in
 /// a separate pass, via `TreeBuilder`.
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub(crate) enum Event {
     /// This event signifies the start of the node.
     /// It should be either abandoned (in which case the
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 03439b784d3..389c01933c9 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -134,10 +134,12 @@ pub(super) fn let_stmt(p: &mut Parser<'_>, with_semi: Semicolon) {
         // test_err let_else_right_curly_brace
         // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
         if let Some(expr) = expr_after_eq {
-            if BlockLike::is_blocklike(expr.kind()) {
-                p.error(
-                    "right curly brace `}` before `else` in a `let...else` statement not allowed",
-                )
+            if let Some(token) = expr.last_token(p) {
+                if token == T!['}'] {
+                    p.error(
+                        "right curly brace `}` before `else` in a `let...else` statement not allowed"
+                    )
+                }
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs
index 75a75f601cf..2f6ba525747 100644
--- a/src/tools/rust-analyzer/crates/parser/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs
@@ -318,7 +318,8 @@ impl Marker {
             _ => unreachable!(),
         }
         p.push_event(Event::Finish);
-        CompletedMarker::new(self.pos, kind)
+        let end_pos = p.events.len() as u32;
+        CompletedMarker::new(self.pos, end_pos, kind)
     }
 
     /// Abandons the syntax tree node. All its children
@@ -336,13 +337,14 @@ impl Marker {
 }
 
 pub(crate) struct CompletedMarker {
-    pos: u32,
+    start_pos: u32,
+    end_pos: u32,
     kind: SyntaxKind,
 }
 
 impl CompletedMarker {
-    fn new(pos: u32, kind: SyntaxKind) -> Self {
-        CompletedMarker { pos, kind }
+    fn new(start_pos: u32, end_pos: u32, kind: SyntaxKind) -> Self {
+        CompletedMarker { start_pos, end_pos, kind }
     }
 
     /// This method allows to create a new node which starts
@@ -360,10 +362,10 @@ impl CompletedMarker {
     /// distance to `NEWSTART` into forward_parent(=2 in this case);
     pub(crate) fn precede(self, p: &mut Parser<'_>) -> Marker {
         let new_pos = p.start();
-        let idx = self.pos as usize;
+        let idx = self.start_pos as usize;
         match &mut p.events[idx] {
             Event::Start { forward_parent, .. } => {
-                *forward_parent = Some(new_pos.pos - self.pos);
+                *forward_parent = Some(new_pos.pos - self.start_pos);
             }
             _ => unreachable!(),
         }
@@ -376,7 +378,7 @@ impl CompletedMarker {
         let idx = m.pos as usize;
         match &mut p.events[idx] {
             Event::Start { forward_parent, .. } => {
-                *forward_parent = Some(self.pos - m.pos);
+                *forward_parent = Some(self.start_pos - m.pos);
             }
             _ => unreachable!(),
         }
@@ -386,4 +388,13 @@ impl CompletedMarker {
     pub(crate) fn kind(&self) -> SyntaxKind {
         self.kind
     }
+
+    pub(crate) fn last_token(&self, p: &Parser<'_>) -> Option<SyntaxKind> {
+        let end_pos = self.end_pos as usize;
+        debug_assert_eq!(p.events[end_pos - 1], Event::Finish);
+        p.events[..end_pos].iter().rev().find_map(|event| match event {
+            Event::Token { kind, .. } => Some(*kind),
+            _ => None,
+        })
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast
new file mode 100644
index 00000000000..578dc2b0f96
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast
@@ -0,0 +1,79 @@
+SOURCE_FILE
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "X"
+    WHITESPACE " "
+    RECORD_FIELD_LIST
+      L_CURLY "{"
+      RECORD_FIELD
+        NAME
+          IDENT "a"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+      R_CURLY "}"
+  WHITESPACE "\n"
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "f"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "foo"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          RECORD_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "X"
+            WHITESPACE " "
+            RECORD_EXPR_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE "\n        "
+              RECORD_EXPR_FIELD
+                NAME_REF
+                  IDENT "a"
+                COLON ":"
+                WHITESPACE " "
+                LITERAL
+                  INT_NUMBER "1"
+              WHITESPACE "\n    "
+              R_CURLY "}"
+          WHITESPACE " "
+          LET_ELSE
+            ELSE_KW "else"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE "\n        "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                  SEMICOLON ";"
+                WHITESPACE "\n    "
+                R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+error 63: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs
new file mode 100644
index 00000000000..c0c0edc9830
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs
@@ -0,0 +1,8 @@
+struct X {a: i32}
+fn f() {
+    let foo = X {
+        a: 1
+    } else {
+        return;
+    };
+}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast
new file mode 100644
index 00000000000..8e994f22d41
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    BIN_EXPR
+      LITERAL
+        INT_NUMBER "1"
+      WHITESPACE " "
+      PLUS "+"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          LITERAL
+            INT_NUMBER "1"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 23: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs
new file mode 100644
index 00000000000..c29ddcce1ff
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs
@@ -0,0 +1,5 @@
+let foo = 1 + {
+    1
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast
new file mode 100644
index 00000000000..055b583acec
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast
@@ -0,0 +1,90 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "r"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "ok"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          MACRO_EXPR
+            MACRO_CALL
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "format_args"
+              BANG "!"
+              TOKEN_TREE
+                L_PAREN "("
+                STRING "\"\""
+                R_PAREN ")"
+          WHITESPACE " "
+          LET_ELSE
+            ELSE_KW "else"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE " "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                  SEMICOLON ";"
+                WHITESPACE " "
+                R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "bad"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          MACRO_EXPR
+            MACRO_CALL
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "format_args"
+              BANG "!"
+              WHITESPACE " "
+              TOKEN_TREE
+                L_CURLY "{"
+                STRING "\"\""
+                R_CURLY "}"
+          WHITESPACE " "
+          LET_ELSE
+            ELSE_KW "else"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE " "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                  SEMICOLON ";"
+                WHITESPACE " "
+                R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 89: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs
new file mode 100644
index 00000000000..5916fa07dc2
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs
@@ -0,0 +1,5 @@
+fn r() {
+    let ok = format_args!("") else { return; };
+
+    let bad = format_args! {""} else { return; };
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast
new file mode 100644
index 00000000000..8c7fd8c295d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast
@@ -0,0 +1,40 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    RANGE_EXPR
+      LITERAL
+        INT_NUMBER "1"
+      DOT2 ".."
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          LITERAL
+            INT_NUMBER "1"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 22: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs
new file mode 100644
index 00000000000..5417131d28e
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs
@@ -0,0 +1,5 @@
+let foo = 1..{
+    1
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast
new file mode 100644
index 00000000000..57925a0d192
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast
@@ -0,0 +1,55 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    CLOSURE_EXPR
+      PARAM_LIST
+        PIPE "|"
+        PARAM
+          IDENT_PAT
+            NAME
+              IDENT "x"
+          COLON ":"
+          WHITESPACE " "
+          PATH_TYPE
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "i32"
+        PIPE "|"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          PATH_EXPR
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "x"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 28: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs
new file mode 100644
index 00000000000..89c7579b071
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs
@@ -0,0 +1,5 @@
+let foo = |x: i32| {
+    x
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast
new file mode 100644
index 00000000000..4fb70bd50e3
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    PREFIX_EXPR
+      MINUS "-"
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          LITERAL
+            INT_NUMBER "1"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 20: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs
new file mode 100644
index 00000000000..1ba7f7d761b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs
@@ -0,0 +1,5 @@
+let foo = -{
+    1
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast
new file mode 100644
index 00000000000..e8eeeee695e
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast
@@ -0,0 +1,90 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "o"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    RET_TYPE
+      THIN_ARROW "->"
+      WHITESPACE " "
+      PATH_TYPE
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "Result"
+            GENERIC_ARG_LIST
+              L_ANGLE "<"
+              TYPE_ARG
+                TUPLE_TYPE
+                  L_PAREN "("
+                  R_PAREN ")"
+              COMMA ","
+              WHITESPACE " "
+              TYPE_ARG
+                TUPLE_TYPE
+                  L_PAREN "("
+                  R_PAREN ")"
+              R_ANGLE ">"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "foo"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          YEET_EXPR
+            DO_KW "do"
+            WHITESPACE " "
+            YEET_KW "yeet"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE "\n        "
+                TUPLE_EXPR
+                  L_PAREN "("
+                  R_PAREN ")"
+                WHITESPACE "\n    "
+                R_CURLY "}"
+          WHITESPACE " "
+          LET_ELSE
+            ELSE_KW "else"
+            WHITESPACE " "
+            BLOCK_EXPR
+              STMT_LIST
+                L_CURLY "{"
+                WHITESPACE "\n        "
+                EXPR_STMT
+                  RETURN_EXPR
+                    RETURN_KW "return"
+                    WHITESPACE " "
+                    CALL_EXPR
+                      PATH_EXPR
+                        PATH
+                          PATH_SEGMENT
+                            NAME_REF
+                              IDENT "Ok"
+                      ARG_LIST
+                        L_PAREN "("
+                        TUPLE_EXPR
+                          L_PAREN "("
+                          R_PAREN ")"
+                        R_PAREN ")"
+                  SEMICOLON ";"
+                WHITESPACE "\n    "
+                R_CURLY "}"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+error 67: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs
new file mode 100644
index 00000000000..188fb07d91b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs
@@ -0,0 +1,7 @@
+fn o() -> Result<(), ()> {
+    let foo = do yeet {
+        ()
+    } else {
+        return Ok(());
+    };
+}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast
new file mode 100644
index 00000000000..cc5e1278c3d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast
@@ -0,0 +1,40 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    BECOME_EXPR
+      BECOME_KW "become"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          TUPLE_EXPR
+            L_PAREN "("
+            R_PAREN ")"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 27: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs
new file mode 100644
index 00000000000..622548b8f33
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs
@@ -0,0 +1,5 @@
+let foo = become {
+    ()
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast
new file mode 100644
index 00000000000..ea2f4f28e2d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    REF_EXPR
+      AMP "&"
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          LITERAL
+            INT_NUMBER "1"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 20: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs
new file mode 100644
index 00000000000..9a00dca3689
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs
@@ -0,0 +1,5 @@
+let foo = &{
+    1
+} else {
+    return;
+};
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast
new file mode 100644
index 00000000000..47396140c5c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast
@@ -0,0 +1,45 @@
+SOURCE_FILE
+  ERROR
+    LET_KW "let"
+    WHITESPACE " "
+    IDENT_PAT
+      NAME
+        IDENT "foo"
+    WHITESPACE " "
+    EQ "="
+    WHITESPACE " "
+    BIN_EXPR
+      PATH_EXPR
+        PATH
+          PATH_SEGMENT
+            NAME_REF
+              IDENT "bar"
+      WHITESPACE " "
+      EQ "="
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          LITERAL
+            INT_NUMBER "1"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    WHITESPACE " "
+    LET_ELSE
+      ELSE_KW "else"
+      WHITESPACE " "
+      BLOCK_EXPR
+        STMT_LIST
+          L_CURLY "{"
+          WHITESPACE "\n    "
+          EXPR_STMT
+            RETURN_EXPR
+              RETURN_KW "return"
+            SEMICOLON ";"
+          WHITESPACE "\n"
+          R_CURLY "}"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 0: expected an item
+error 25: right curly brace `}` before `else` in a `let...else` statement not allowed
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs
new file mode 100644
index 00000000000..08e677416f1
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs
@@ -0,0 +1,5 @@
+let foo = bar = {
+    1
+} else {
+    return;
+};