about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/event.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs10
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/parser.rs4
5 files changed, 10 insertions, 13 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.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index fe6b904bd88..d3aa56c7ebd 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -204,8 +204,9 @@ impl BlockLike {
         self == BlockLike::Block
     }
 
-    fn is_blocklike(kind: SyntaxKind) -> bool {
-        matches!(kind, BLOCK_EXPR | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR)
+    fn is_blocklike(expr: &CompletedMarker, p: &Parser<'_>) -> bool {
+        matches!(expr.kind(), BLOCK_EXPR | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR)
+            || (expr.last_token(p) == Some(T!['}']) && !matches!(expr.kind(), CLOSURE_EXPR))
     }
 }
 
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 6494ce8d718..e7ba33bcb64 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -134,12 +134,10 @@ 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 let Some(token) = expr.last_token(p) {
-                if token == T!['}'] {
-                    p.error(
-                        "right curly brace `}` before `else` in a `let...else` statement not allowed"
-                    )
-                }
+            if BlockLike::is_blocklike(&expr, p) {
+                p.error(
+                    "right curly brace `}` before `else` in a `let...else` statement not allowed",
+                )
             }
         }
 
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 407320e1d08..40705d4a392 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
@@ -198,7 +198,7 @@ pub(super) fn atom_expr(
         }
     };
     let blocklike =
-        if BlockLike::is_blocklike(done.kind()) { BlockLike::Block } else { BlockLike::NotBlock };
+        if BlockLike::is_blocklike(&done, p) { BlockLike::Block } else { BlockLike::NotBlock };
     Some((done, blocklike))
 }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs
index 832ba8d23a3..2f6ba525747 100644
--- a/src/tools/rust-analyzer/crates/parser/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs
@@ -391,9 +391,7 @@ impl CompletedMarker {
 
     pub(crate) fn last_token(&self, p: &Parser<'_>) -> Option<SyntaxKind> {
         let end_pos = self.end_pos as usize;
-        if end_pos > p.events.len() {
-            return None;
-        }
+        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,