From 4779d69de6bf9c3642725e2fcdb2afa2ab37ed7d Mon Sep 17 00:00:00 2001 From: Solomon Date: Tue, 4 Mar 2025 11:34:34 +0000 Subject: [PATCH] prevent panic when parsing incomplete multi-expr (`|`) matches (#15230) Fixes #14971, fixes #15229 # User-Facing Changes Fixes a panic when variable data is accessed after invalid usage of the `|` separator, which made it impossible to type certain match arms: ```nushell > match $in { 1 | Error: x Main thread panicked. |-> at crates/nu-protocol/src/engine/state_delta.rs:100:14 `-> internal error: missing required scope frame ``` # Description Removes duplicative calls to `exit_scope` from an inner loop when `|` parse errors are encountered. The outer loop creates and exits scopes for each match arm. --- crates/nu-command/tests/commands/match_.rs | 7 +++++++ crates/nu-parser/src/parser.rs | 4 ---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/tests/commands/match_.rs b/crates/nu-command/tests/commands/match_.rs index 5d41b3291a..7bf61e8853 100644 --- a/crates/nu-command/tests/commands/match_.rs +++ b/crates/nu-command/tests/commands/match_.rs @@ -244,6 +244,13 @@ fn match_with_guard_no_expr_after_if() { assert!(actual.err.contains("Match guard without an expression")); } +#[test] +fn match_with_or_missing_expr() { + let actual = nu!("match $in { 1 | }"); + + assert!(actual.err.contains("expected pattern")); +} + #[test] fn match_with_comment_1() { Playground::setup("match_with_comment", |dirs, _| { diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 32ec9d3ce9..358a3a5575 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -4680,8 +4680,6 @@ pub fn parse_match_block_expression(working_set: &mut StateWorkingSet, span: Spa "end of input".into(), Span::new(output[position - 1].span.end, output[position - 1].span.end), )); - - working_set.exit_scope(); break; } @@ -4695,8 +4693,6 @@ pub fn parse_match_block_expression(working_set: &mut StateWorkingSet, span: Spa "end of input".into(), Span::new(output[position - 1].span.end, output[position - 1].span.end), )); - - working_set.exit_scope(); break; } else { connector = working_set.get_span_contents(output[position].span);