Skip to content

Reproduce autoloader bug#4003

Draft
staabm wants to merge 2 commits into
phpstan:2.2.xfrom
staabm:bug12972b
Draft

Reproduce autoloader bug#4003
staabm wants to merge 2 commits into
phpstan:2.2.xfrom
staabm:bug12972b

Conversation

@staabm

@staabm staabm commented May 21, 2025

Copy link
Copy Markdown
Contributor

this test demonstrates how PHPStan analyzes code differently than it would happen at runtime.


runtime: run php real-world.php
you see the program runs, without the custom autoloader of e2e/bug-12972b/autoloader.php beeing invoked.
all involved classes are autoloaded by the composer class loader. the custom class loader is not invoked for \other12972\MyClass::class.


static analysis time: run ../../bin/phpstan analyze

you see PHPStan invokes the custom class loader for class \other12972\MyClass::class, which does not happen at regular runtime. the composer class loader is not invoked for \other12972\MyClass::class (like it is at runtime).

because of the difference in autoloading functions order in runtime vs. analysis time we see errors which cannot happen at runtime - see phpstan/phpstan#12972


spl_autoload_register(function($class) {
if ($class === \other12972\MyClass::class) {
throw new LogicException('this should not happen');

@staabm staabm May 21, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in our real world project this autoloader is scanning some paths in the filesystem (similar to how a include-path worked in the past / or how the %PATH% variable works in a shell).

since it scans the filesystem it finds some files and includes them. this in turn leads to the problem described in phpstan/phpstan#12972 -> so invoking the autoloader leads side-effects, as files get included, which has impact on ReflectionClass->getFileName() invoked later on in PHPStan

@staabm
staabm changed the base branch from 2.1.x to 2.2.x July 20, 2026 14:22
# host and only the build and test commands run inside a long-lived
# Alpine container via docker exec — native arm64, no QEMU. The steps
# mirror the musl leg of turbo-compile one for one.
runs-on: "ubuntu-24.04-arm"

- name: "Install bashunit"
run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.37.0"
uses: "TypedDevs/bashunit@ffa9c79e71ecbb9990e777348bc9ba12314b62d0" # 0.39.1

- name: "Install bashunit"
run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.37.0"
uses: "TypedDevs/bashunit@ffa9c79e71ecbb9990e777348bc9ba12314b62d0" # 0.39.1
fetch-depth: 0 # git log over turbo-ext/src needs full history

- name: "Install PHP"
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
fetch-depth: 0 # the VERSION.txt written below bakes from git log over turbo-ext/src

- name: "Install PHP"
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
fetch-depth: 0

- name: "Install PHP"
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
git -C /c/php-sdk checkout -q "$PHP_SDK_COMMIT"

- name: "Set up MSVC environment"
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
WANT_ZTS=$([ "${{ matrix.ts }}" = "zts" ] && echo 1 || echo 0)
[ "$(php -r 'echo (int) ((bool) PHP_ZTS);')" = "$WANT_ZTS" ]

- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
persist-credentials: false

- name: "Install PHP"
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
fi
php -m | grep phpstan_turbo

- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
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.

2 participants