Skip to content

Keep the pre-autoloader turbo code polyfill-free and skip the extension lookup on PHP < 8.3 - #6319

Merged
ondrejmirtes merged 3 commits into
2.2.xfrom
turbo-restart-php74
Aug 31, 2026
Merged

ondrejmirtes merged 3 commits into
2.2.xfrom
turbo-restart-php74

Conversation

@ondrejmirtes

Copy link
Copy Markdown
Member

bin/phpstan requires the turbo restart classes and calls TurboProcessRestarter::restartIfSuitable() before vendor/autoload.php, so the symfony polyfills are not registered yet when they run. 51d272f put str_contains() into TurboExtensionSelector::resolveIsMusl(), which fatals the phar on PHP 7.4 hosts with pcntl — reached on Linux only, where /proc/self/maps exists:

PHP Fatal error:  Uncaught Error: Call to undefined function str_contains() in phar:///.../phpstan.phar/src/Turbo/TurboExtensionSelector.php:113

Nothing in CI caught it: the phpstan/phpstan e2e jobs that run the phar on 7.4 use setup-php's ini-file: development, which lists the pcntl functions in disable_functions, so the restarter returned before ever calling findExtension().

  • TurboExtensionSelector::findExtension() returns early on PHP < 8.3 (MINIMUM_PHP_VERSION_ID, the turbo-compile matrix floor): there is no binary to find, so neither the restart nor worker spawning probes the filesystem there, and diagnose says so.
  • resolveIsMusl() uses strpos(); PreAutoloadFilesTest derives the files bin/phpstan loads before the autoloader and fails on any call to a function declared by vendor/symfony/polyfill-* — the same class of crash would hit PHP 8.3 with the extension loaded for a polyfill-php84/85 function, which no e2e run exercises.
  • New phar-run job in phar.yml runs the compiled phar (--version + analyse -vvv on e2e/phar-run) on PHP 7.4–8.5 with pcntl available, asserting pcntl_exec exists so it cannot pass vacuously. Reproduced locally in Docker php:7.4-cli + pcntl: the unfixed phar fatals exactly as above; a phar with only the version gate passes, as does the full change.
  • SkipTestsWithRequiresPhpAttributeRule threw ShouldNotHappenException for a test method whose first statement is if ($a || $b); the PHP_VERSION_ID checks now precede the operator switch (with a test).

Closes phpstan/phpstan#15137

🤖 Generated with Claude Code

https://claude.ai/code/session_012bBnhEMLHeUbbAENSRYK6u

…sWithRequiresPhpAttributeRule

The rule threw ShouldNotHappenException for any TestCase method whose first statement is an if with a non-comparison binary operator in its condition, such as if ($a || $b).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012bBnhEMLHeUbbAENSRYK6u
# the phar boots through the turbo restart code, which bin/phpstan
# loads before the Composer autoloader - on PHP < 8.0 without the
# symfony polyfills (https://github.com/phpstan/phpstan/issues/15137).
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
ondrejmirtes and others added 2 commits August 31, 2026 17:05
…-free

bin/phpstan requires TurboExtensionEnabler, TurboExtensionSelector and TurboProcessRestarter and calls restartIfSuitable() before vendor/autoload.php, so the symfony polyfills are not registered yet when they run. The str_contains() in resolveIsMusl() fataled the phar on PHP 7.4 hosts with pcntl - on Linux only, where /proc/self/maps exists.

PreAutoloadFilesTest derives the files bin/phpstan loads before the autoloader and the functions vendor/symfony/polyfill-* declares, and fails on any call. The new phar-run job runs the compiled phar on PHP 7.4-8.5 with pcntl available: the phpstan/phpstan e2e jobs use setup-php's ini-file: development, which lists the pcntl functions in disable_functions, so the restarter returned before ever reaching findExtension() there.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012bBnhEMLHeUbbAENSRYK6u
The extension is built for PHP >= 8.3 only (the phar.yml turbo-compile matrix), so on older runtimes findExtension() - the process restart and worker spawning - returns before probing the filesystem and /proc/self/maps, and diagnose says why no binary was found.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012bBnhEMLHeUbbAENSRYK6u
@ondrejmirtes
ondrejmirtes merged commit 9581b01 into 2.2.x Aug 31, 2026
803 of 815 checks passed
@ondrejmirtes
ondrejmirtes deleted the turbo-restart-php74 branch August 31, 2026 15:51
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.

PHP Fatal error: Uncaught Error: Call to undefined function str_contains() in phar:///.../phpstan.phar/src/Turbo/TurboExtensionSelector.php:113

2 participants