Bug #22314
openparse.y does not check **rest bindings in patterns (duplicate / alternation)
Description
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¶
No data to display