From cb303ff4b82dca932cb7342e9f7fd337d69dc175 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 6 Dec 2025 08:48:29 +0900 Subject: [Bug #21669] Fix void value expression check for pattern-matching If the all `in` and `else` branches are void, the `case` is also void. --- parse.y | 26 ++++++++++++++++++-------- test/ruby/test_syntax.rb | 12 ++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/parse.y b/parse.y index a872eb61a3..b874e4f8dc 100644 --- a/parse.y +++ b/parse.y @@ -13877,15 +13877,25 @@ value_expr_check(struct parser_params *p, NODE *node) break; case NODE_CASE3: - if (!RNODE_CASE3(node)->nd_body || !nd_type_p(RNODE_CASE3(node)->nd_body, NODE_IN)) { - compile_error(p, "unexpected node"); - return NULL; - } - if (RNODE_IN(RNODE_CASE3(node)->nd_body)->nd_body) { - return NULL; + { + NODE *in = RNODE_CASE3(node)->nd_body; + if (!in || !nd_type_p(in, NODE_IN)) { + compile_error(p, "unexpected node"); + return NULL; + } + if (!RNODE_IN(in)->nd_body) { + /* single line pattern matching with "=>" operator */ + goto found; + } + do { + vn = value_expr_check(p, RNODE_IN(in)->nd_body); + if (!vn) return NULL; + if (!void_node) void_node = vn; + in = RNODE_IN(in)->nd_next; + } while (in && nd_type_p(in, NODE_IN)); + node = in; /* else */ } - /* single line pattern matching with "=>" operator */ - goto found; + break; case NODE_BLOCK: while (RNODE_BLOCK(node)->nd_next) { diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 1ea646d216..e868967e8b 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -2132,6 +2132,18 @@ eom }; end + def test_value_expr_in_case3 + assert_syntax_error("#{<<~"{#"}\n#{<<~'};'}", /void value expression/, nil, "#{BUG_21669} 1.3") + {# + x = + case a + in 1; return + in 2; return + else return + end + }; + end + def test_tautological_condition assert_valid_syntax("def f() return if false and invalid; nil end") assert_valid_syntax("def f() return unless true or invalid; nil end") -- cgit v1.2.3