summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2025-12-06 08:48:29 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2026-02-04 13:28:34 +0900
commitcb303ff4b82dca932cb7342e9f7fd337d69dc175 (patch)
tree71897d1c0ddfbc78c0398f4358ceb0822ab03e86
parentbaaf0ccb9c74d902d834c821c4d7e17e4bac4694 (diff)
[Bug #21669] Fix void value expression check for pattern-matching
If the all `in` and `else` branches are void, the `case` is also void.
-rw-r--r--parse.y26
-rw-r--r--test/ruby/test_syntax.rb12
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")