Skip to content

Skip PhpParser\NodeTraverser in preload.php when it is already declared - #8689

Merged
TomasVotruba merged 1 commit into
rectorphp:mainfrom
SanderMuller:preload-guard-node-traverser
Oct 18, 2026
Merged

TomasVotruba merged 1 commit into
rectorphp:mainfrom
SanderMuller:preload-guard-node-traverser

Conversation

@SanderMuller

Copy link
Copy Markdown
Contributor

PHPStan Turbo declares a native PhpParser\NodeTraverser when it is activated. Rector has to activate it before preload.php runs, because Turbo cannot replace a class that is already declared. The plain require_once of php-parser's NodeTraverser.php in preload.php then fails with "Cannot redeclare class PhpParser\NodeTraverser".

build/build-preload.php now wraps that one line in if (! class_exists(NodeTraverser::class, false)), the same way the template already checks PHPStanTestCase. preload.php is regenerated with composer preload. Without Turbo the class is not declared yet, so preload.php loads it as before.

This prepares for loading Turbo in bin/rector.php. That part needs PHPStan 2.3.2, for phpstan/phpstan-src#6720. A proof of concept is on https://github.com/SanderMuller/rector-src/tree/turbo-poc.

I ran a cold bin/rector process --dry-run --clear-cache on rector-src itself, with 14 workers. It takes 8.2 s instead of 11.6 s, and 61 s of CPU instead of 100 s. Those are medians of 5 runs on an M4 Pro with PHP 8.5. The output is the same in all runs.

PHPStan Turbo declares a native PhpParser\NodeTraverser when it is
activated. preload.php then fails with "Cannot redeclare class". Without
Turbo, the class is not declared yet and preload.php loads it as before.
@TomasVotruba
TomasVotruba merged commit 2809e3f into rectorphp:main Oct 18, 2026
49 checks passed
@TomasVotruba

Copy link
Copy Markdown
Member

Thank you, can't wait to test this one 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants