Repository navigation
Conversation
phcorp
marked this pull request as ready for review
November 8, 2026 20:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PHP lets a
matcharm end its condition list with a trailing comma, and allows the same comma afterdefault. The PHP grammar rules arematch_arm_cond_list possible_comma T_DOUBLE_ARROW exprandT_DEFAULT possible_comma T_DOUBLE_ARROW expr. elephc rejected both forms:'a', 'b', => …failed withExpected '=>' in match armdefault, => …failed withExpected '=>' after 'default'Both forms now parse and run as they do in PHP. A comma that has no condition before it (
, =>), and a doubled comma (1,, =>,default,, =>), are still rejected, as PHP rejects them.Found while compiling a Symfony/TUI application:
janalis/vizuses this form.Repro
error: Expected '=>' in match arm(andExpected '=>' after 'default'for the second form)rectcd/1rectcd/1Inputs that are still rejected, on this branch and in PHP:
match (1) { , => 1, default => 2 }unexpected token ","Unexpected token: Commamatch (1) { 1,, => 1, default => 2 }unexpected token ","Unexpected token: Commamatch (1) { 1, default => 1 }unexpected token "default"Unexpected token: Defaultmatch (1) { default,, => 1 }Expected '=>' after 'default'How it works
parse_match_expr:Condition list. Before the fix, the parser met
,followed by=>, then moved the cursor back to the comma before leaving the condition loop. The=>check that comes next therefore saw the comma. The parser now consumes the comma and leaves the loop with the cursor on=>:default. One optional comma is consumed before the existing=>check. A second comma still fails that check.Tests
test_parse_match_arm_condition_list_trailing_comma(parser): a multi-line list, a single condition anddefaulteach take a trailing comma. Every condition stays on its arm.test_match_arm_condition_list_trailing_comma(codegen): all three forms compile and dispatch the right arm (rect|rect|circle|none). The output matches PHP underELEPHC_PHP_CHECK=1.test_error_match_arm_lone_comma,test_error_match_arm_double_trailing_comma,test_error_match_default_double_trailing_comma(errors): stray commas are still rejected.Run against main's parser, the parser test and the codegen test fail with
Expected '=>' in match arm. Runs on this branch:cargo test --test parser_tests match_arm: 1 passedcargo test --test error_tests test_error_match: 5 passedELEPHC_PHP_CHECK=1 cargo test --test codegen_tests test_match_arm_condition_list_trailing_comma: 1 passedNote
CI status: this PR comes from a fork, so the
CI,PDO Live DatabasesandPHP extension host SDKworkflows are waiting for maintainer approval (action_required). The focused tests above ran locally on macOS arm64, and the codegen tests were also compared with PHP 8.5.12 (ELEPHC_PHP_CHECK=1). This is a front-end change (parser/checker only) with no target-specific code.Limits
eval()parser incrates/elephc-magicianis separate and still rejects the form:eval('return match (2) { 1, 2, => "a", default => "b" };')fails withParse error: eval() fragment is invalid.Follow-ups
eval()parser (match arms anddefault).src/parser/expr/prefix_complex.rs, in different functions (parse_match_exprandparse_closure), and both add tests totests/error_tests/syntax.rsat different places. A scratch merge of the two branches is clean, and the combined parser and error tests pass. The PRs can merge in either order.