Skip to content

Only report real captures inside alternation patterns - #4236

Merged
kddnewton merged 1 commit into
ruby:mainfrom
yuki-300:fix/alternation-capture
Sep 28, 2026
Merged

kddnewton merged 1 commit into
ruby:mainfrom
yuki-300:fix/alternation-capture

Conversation

@yuki-300

Copy link
Copy Markdown
Contributor

When a variable is captured anywhere in a pattern, Prism also reports underscore-prefixed names and local variable targets inside lambdas, string interpolation and pinned expressions as captures in an alternation:

case foo
in [bar, 1 | _baz]                       # variable capture in alternative pattern
in [bar, -> { case 1; in baz; end } | 2] # same
end

Both are accepted without bar. This skips underscore-prefixed names like parse_pattern_capture does and only visits the nodes that make up the pattern. Nested alternations are skipped as well since their operands were already checked when they were parsed. That also gets rid of the double error for in [x, (1 | y) | 2].

The new fixture is excluded from the parse.y comparisons. parse.y currently rejects these forms for a different reason (https://bugs.ruby-lang.org/issues/22310, fix proposed in ruby/ruby#18830) and the exclusions can go once that lands.

Fixes #4235

When a variable is captured anywhere in a pattern, the operands of each
alternation are visited to report captures inside them. That visitor
treated every local variable target as a capture, including
underscore-prefixed names and targets that belong to a lambda, a string
interpolation, or a pinned expression:

    case foo
    in [bar, 1 | _baz]                         # error
    in [bar, "#{case 1; in baz; end}" | 2]     # error
    end

Without `bar` both are accepted. Skip underscore-prefixed names, like
parse_pattern_capture does, and only descend into the nodes that make up
the pattern itself. Nested alternations are skipped too, their operands
were already checked when they were parsed. Before this, a capture like
`1 => [x, (1 | y) | 2]` was reported twice.

The new fixture is excluded from the tests that compare against parse.y,
which currently rejects these forms because of the capture of `bar`:
https://bugs.ruby-lang.org/issues/22310
@kddnewton
kddnewton merged commit 09eb621 into ruby:main Sep 28, 2026
110 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Alternation capture check rejects underscore names and captures from other scopes

2 participants