Skip to content

Revert the bootstrap autoloader execution changes - #6292

Merged
ondrejmirtes merged 5 commits into
2.2.xfrom
revert-bootstrap-autoloader-fixes
Aug 27, 2026
Merged

Revert the bootstrap autoloader execution changes#6292
ondrejmirtes merged 5 commits into
2.2.xfrom
revert-bootstrap-autoloader-fixes

Conversation

@ondrejmirtes

@ondrejmirtes ondrejmirtes commented Aug 27, 2026

Copy link
Copy Markdown
Member

Reverts the five bootstrap-autoloader commits, keeping every e2e test they added so the repo keeps documenting which shapes regress:

The touched files are back to their 2.2.8 state, except bin/phpstan (keeps the TurboProcessRestarter lines) and the bootstrapFiles flow: the collection loop that used to live inline in CommandHelper::begin() now lives in BootstrapFilesRunner::mergeNewAutoloadFunctions() (per-forked-worker bootstrapFiles stay), restored to the 2.2.8 semantics — every newly registered autoloader is appended to $GLOBALS['__phpstanAutoloadFunctions'], no prepended/appended split.

Local e2e results after the revert:

e2e test result
bug-14988 ❌ child process fatal: Cannot redeclare function Redeclare\Builder\thing() — workflow step commented out
bug-12972b ❌ internal error: the eagerly-run bootstrap autoloader's own guard exception aborts analysis — workflow step commented out
bug-12972c
bug-15102
bug-15102b
bug-15102c

The two failing steps are commented out in e2e-tests.yml (their e2e projects stay in the repo), so CI on this PR is expected to be green. Both tests were added by the commits being reverted — they cover behavior 2.2.8 never had.

Unit tests, coding standard, lint and PHPStan self-analysis are green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS

ondrejmirtes and others added 5 commits August 27, 2026 21:18
…k for, running them for real only when that cannot redeclare a symbol"

This reverts commit 598faaa, keeping
the bug-15102c e2e test and its workflow entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS
This reverts commit c10897b, keeping
the bug-15102 e2e test and its workflow entry. It also reverts
9680cc4 (Use early exit when
collecting the registered class loaders), which only restyled the
code being reverted here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS
…a loaded file"

This reverts commit 7fde888.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS
…e static source locators (#6069)"

This reverts commit f896750, keeping
the bug-12972b and bug-12972c e2e tests. The bug-12972b workflow step
is commented out - without the reverted fix, the eagerly-run bootstrap
autoloader's own guard exception aborts the analysis again.

BootstrapFilesRunner::mergeNewAutoloadFunctions() - extracted from
CommandHelper::begin() when bootstrapFiles started running per forked
worker - goes back to the inline pre-revert collection: every newly
registered autoloader is appended to $GLOBALS['__phpstanAutoloadFunctions'],
with no prepended/appended split around the project's class loader.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS
#6185)"

This reverts commit 8e2efc0, keeping
the bug-14988 e2e test. Its workflow step is commented out - without
the reverted fix, a bootstrap autoloader re-includes an already loaded
file and the child process dies with a redeclare fatal again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHfXXuWi9gKZ8daM2CeAyS
@ondrejmirtes

Copy link
Copy Markdown
Member Author

/cc @SanderMuller @staabm

This will reopen phpstan/phpstan#14976 and phpstan/phpstan#14988 but otherwise everything broken after #6069 and #6185 keeps working.

Besides reported issues in phpstan/phpstan#15102 (from which we are keeping the E2E tests) the fix attempts also broke various popular class loaders like in TYPO3, Larastan and also RobotLoader.

As I said somewhere else, every intervention in BetterReflectionSourceLocatorFactory will fix one use case but break another, it's inevitable as the current ordering definitely works for some unknown percentage of PHPStan users. To me it's important not to break PHPStan working for people out there.

Of course you're welcome to try solving phpstan/phpstan#14976 and phpstan/phpstan#14988 in the future, but it won't be easy.

Thank you for understanding.

@ondrejmirtes
ondrejmirtes merged commit 22967f3 into 2.2.x Aug 27, 2026
760 of 768 checks passed
@ondrejmirtes
ondrejmirtes deleted the revert-bootstrap-autoloader-fixes branch August 27, 2026 19:49
@SanderMuller

SanderMuller commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Understood, and agreed on the constraint - a fix that trades one working setup for another is not a fix.

Starting from the other end then: #6293 adds e2e coverage for the two loader shapes that broke, using the real packages, so a future attempt at #14976/#14988 has a gate instead of waiting for user reports. Test-only, src/ untouched.

project 2.2.9 (#6069 + #6185) 598faaade (#6287 series) current tip
class-alias-loader (real typo3/class-alias-loader + an IDE stub in paths) 1 error No errors No errors
robot-loader (Nette RobotLoader over a directory Composer does not map) No errors Internal error No errors

The RobotLoader one is the shape I wish had existed before any of this: on 598faaade it dies in RobotLoader::acquireLock() with Unable to create file '<tmp>/....php.lock', because RobotLoader locks and writes a cache file while resolving and the file-read trap has replaced the file wrapper. (I first quoted a different lock message here - that one comes from nette/di; the trace shows RobotLoader's own lock.) None of the existing projects covered an autoloader that writes during resolution.

With those in place the gate for a retry is explicit: turn bug-14988 and bug-12972b green without turning class-alias-loader, robot-loader, bug-12972c, bug-15102, bug-15102b or bug-15102c red. I have no patch that clears that bar yet, and I would rather have the bar in the repo than another attempt.

Also: I corrected phpstan/phpstan#15118 - baseline is empty now (the five class.nameCase errors were #6271, gated since e07268440), and the framing points at #14976 rather than #15102 as you noted.

SanderMuller added a commit to SanderMuller/phpstan-src that referenced this pull request Aug 27, 2026
phpstan#6292 reverted five commits because the attempts fixed one use case and
broke another, and only some of those breakages had an e2e project. These
two do not test PHPStan's current behaviour so much as pin the shapes a
future attempt at phpstan/phpstan#14976 and phpstan/phpstan#14988 must not
regress.

class-alias-loader uses the real typo3/class-alias-loader: it replaces
Composer's loader with its own wrapper, resolves a legacy name through a
class alias map, and an IDE-only stub in the analysed paths declares that
name as a plain class. The alias has to win. 2.2.9 returns the stub and
reports a missing method.

robot-loader registers a Nette RobotLoader over a directory Composer does
not map, so only that loader can find the class. RobotLoader locks and
writes a cache file while resolving, which fails inside the file-read trap:
on 598faaa the analysis dies in RobotLoader::acquireLock() with
"Unable to create file '<tmp>/....php.lock'".

Both pass on this commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ondrejmirtes pushed a commit that referenced this pull request Aug 27, 2026
#6292 reverted five commits because the attempts fixed one use case and
broke another, and only some of those breakages had an e2e project. These
two do not test PHPStan's current behaviour so much as pin the shapes a
future attempt at phpstan/phpstan#14976 and phpstan/phpstan#14988 must not
regress.

class-alias-loader uses the real typo3/class-alias-loader: it replaces
Composer's loader with its own wrapper, resolves a legacy name through a
class alias map, and an IDE-only stub in the analysed paths declares that
name as a plain class. The alias has to win. 2.2.9 returns the stub and
reports a missing method.

robot-loader registers a Nette RobotLoader over a directory Composer does
not map, so only that loader can find the class. RobotLoader locks and
writes a cache file while resolving, which fails inside the file-read trap:
on 598faaa the analysis dies in RobotLoader::acquireLock() with
"Unable to create file '<tmp>/....php.lock'".

Both pass on this commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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