Skip to content

Update nikic/PHP-Parser to 5.9.0 - #6498

Merged
ondrejmirtes merged 3 commits into
2.2.xfrom
update-php-parser-5.9
Sep 21, 2026
Merged

ondrejmirtes merged 3 commits into
2.2.xfrom
update-php-parser-5.9

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

Updates nikic/PHP-Parser from 5.8.0 to 5.9.0, together with the turbo-ext native parser engine.

turbo-ext

  • Regenerated the reduce actions (generate-parser-actions.php) for 5.9's new argument-list grammar: ArgPlaceholder nodes for ?, and ... allowed in any argument position. The generator needed no new hand-written overrides. ArgPlaceholder has a trivial constructor, so it gets direct property writes.
  • Ported the tighter \u{...} escape limit (0x10FFFF, was 0x1FFFFF) to the native parseEscapeSequences().
  • Nothing else in the engine changed: the ParserAbstract.php diff is doc comments only, and the new @hexdec in Float_ only silences a PHP 8.6 warning, which the native port never emits.
  • Pins: SUPPORTED_PHP_PARSER_VERSION is now v5.9.0 and EXPECTED_EXTENSION_VERSION is 0867753.
  • New fixtures in turbo-ext/tests/parser-fixtures/ for partial function application and both sides of the \u{10FFFF} limit.
  • New test turbo-ext/tests/parser-upstream-corpus.php: runs the same native-vs-PHP comparison over every input php-parser's own test suite parses (parser, pretty-printer and format-preservation cases). It fetches the installed commit from GitHub, or takes a checkout path. CI runs it next to parser-corpus.php. The shared comparison moved to parser-compare.php.

Verification (PHP 8.5, macOS arm64)

  • parser-corpus.php: 8,466 files, 0 differences.
  • parser-upstream-corpus.php: 524 upstream cases, 0 differences.
  • The checks catch a stale engine:
    • With the old 0x1FFFFF limit, the new fixtures fail, and so does upstream's unicodeEscape.test #3.
    • With the 5.8 reduce actions against the 5.9 tables, the corpus run segfaults.
  • Full test suite with and without the extension: 21,576 tests green in both.
  • make phpstan with and without the extension: no errors in both.
  • Level 9 analysis of src plus 5 vendored libraries is identical with and without the extension (3,739 lines). The only difference is PHPStanTurbo\Runtime, a class that only exists when the extension is loaded.
  • smoke.php, signature-parity.php and side-by-side.php --check pass.
  • parser-bench.php: native parsing 2.8× faster than PHP (0.354s vs 0.997s user).

Known issue: partial function application

5.9 parses PHP 8.6 partial function application, e.g. foo(?), foo(1, ...), new A(?), A::s(?). With 5.8 these were syntax errors. PHPStan now crashes with an internal error on each of these forms, with or without the extension. Examples:

  • ArrayMapArgVisitor calls setAttribute() on null
  • MutatingScope::getType() gets null
  • ParametersAcceptorSelector calls getAttribute() on null
  • ArgumentsNormalizer builds an Arg with a null value

This PR doesn't handle it. The follow-up is either reporting this syntax as unsupported or implementing support for it.

🤖 Generated with Claude Code

https://claude.ai/code/session_017ZXwmsVRBa9PE9htEXAnwo

ondrejmirtes and others added 3 commits September 21, 2026 17:18
Regenerated the native parser engine's reduce actions for the new
argument-list grammar (ArgPlaceholder, "..." in any argument position)
and ported the tightened \u{...} escape limit (0x10FFFF) to the native
String_::parseEscapeSequences(). Corpus fixtures cover both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ZXwmsVRBa9PE9htEXAnwo
tests/parser-upstream-corpus.php parses every input php-parser's test
suite parses (parser, pretty-printer and format-preservation cases) with
both engines, fetching the installed commit from GitHub or taking a
checkout. Upstream's cases cover every grammar rule, error recovery and
version-gated behavior, including syntax PHPStan's own code does not use
yet. The comparison moves to parser-compare.php, shared with
parser-corpus.php.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ZXwmsVRBa9PE9htEXAnwo
@ondrejmirtes
ondrejmirtes merged commit ebc6a3b into 2.2.x Sep 21, 2026
532 of 536 checks passed
@ondrejmirtes
ondrejmirtes deleted the update-php-parser-5.9 branch September 21, 2026 15:59
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.

1 participant