From: "yuki300 (Yuki Hiro) via ruby-core" Date: 2026-09-14T19:02:53+00:00 Subject: [ruby-core:126699] [Ruby Bug#22314] parse.y does not check **rest bindings in patterns (duplicate / alternation) Issue #22314 has been reported by yuki300 (Yuki Hiro). ---------------------------------------- Bug #22314: parse.y does not check **rest bindings in patterns (duplicate / alternation) https://bugs.ruby-lang.org/issues/22314 * Author: yuki300 (Yuki Hiro) * Status: Open * ruby -v: ruby 4.0.4 (2026-05-12 revision b89eb1bcbf) +PRISM [arm64-darwin25] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- `p_kwrest` is the only binding rule in patterns that does not go through `error_duplicate_pattern_variable`. `p_variable`, `p_rest` and the `{a:}` shorthand in `p_kw` all call it before `assignable`; for `**rest` the name is handed straight to `assignable` in `new_hash_pattern_tail`. So `**rest` is never registered in `pvtbl`, never checked against `in_alt_pattern`, and never sets `capture_in_pattern`. ## Duplicate binding case { a: 1, b: 2 } in { a: x, **x } then p x end $ ruby --parser=parse.y dup.rb {b: 2} # accepted and runs; x is the rest hash $ ruby --parser=prism dup.rb dup.rb:2: duplicated variable name (SyntaxError) `in a, a` and `in a, {a:}` are rejected by parse.y as expected; only `**rest` slips through. This is not a 4.0 regression: parse.y in 3.4.9 also accepts it, and Prism 3.4.9 already rejects it. ## Binding inside an alternative pattern case 1 in 1 | { a: 1, **rest } end $ ruby --parser=parse.y -c alt.rb Syntax OK $ ruby --parser=prism -c alt.rb alt.rb:2: variable capture in alternative pattern (SyntaxError) $ ruby --parser=parse.y alt.rb # compile.c still catches it at run time alt.rb:2: illegal variable in alternative pattern (rest) `*rest` in the same position is rejected at parse time by both parsers. This form only diverges since 4.0, where https://bugs.ruby-lang.org/issues/21572 moved the check to parse time; in 3.4.9 both parsers accept it under `-c` and reject it at compile time. ## Fix Call `error_duplicate_pattern_variable` in `p_kwrest`, as `p_rest` does. One line plus tests: https://github.com/ruby/ruby/pull/18831 It should land after the fix for https://bugs.ruby-lang.org/issues/22310 (https://github.com/ruby/ruby/pull/18830): on its own, making `**rest` set `capture_in_pattern` would newly reject an unrelated sibling alternation such as `in [ { **rest }, 1 | 2 ]` under the current `p_alt` check. With that fix applied first, both parsers agree on every form I tried. Since this turns code parse.y has accepted at least since 3.4 into a SyntaxError, I am not requesting a backport. ## Environment ruby 4.0.4 (2026-05-12 revision b89eb1bcbf) +PRISM [arm64-darwin25] # rejects with --parser=prism only ruby 3.4.9 (2026-03-11 revision 76cca827ab) +PRISM [arm64-darwin25] # duplicate case: same divergence -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/