Skip to content

Cover the loader shapes the reverted autoloader attempts broke - #6293

Merged
ondrejmirtes merged 1 commit into
phpstan:2.2.xfrom
SanderMuller:e2e-autoloader-shapes
Aug 27, 2026
Merged

Cover the loader shapes the reverted autoloader attempts broke#6293
ondrejmirtes merged 1 commit into
phpstan:2.2.xfrom
SanderMuller:e2e-autoloader-shapes

Conversation

@SanderMuller

@SanderMuller SanderMuller commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Test-only. No behaviour change - src/ is untouched.

#6292 reverted five commits because, as you put it, every intervention in this area fixes one use case and breaks another. The problem for a future attempt is that only some of those breakages had an e2e project, so the next person gets no signal until a user reports it. These two projects pin the shapes that actually broke, using the real loaders rather than hand-rolled stand-ins.

project 2.2.9 (#6069 + #6185) 598faaade (#6287 series) this commit
class-alias-loader 1 error No errors No errors
robot-loader No errors Internal error No errors

Between them they cover both eras of breakage, and neither duplicates an existing project.

class-alias-loader uses the real typo3/class-alias-loader with always-add-alias-loader: it takes Composer's loader out of the queue and puts its own wrapper in, resolves a legacy name through a class alias map, and an IDE-only stub inside the analysed paths declares that same name as a plain class without the method. The alias has to win. On 2.2.9 the stub wins and PHPStan reports a missing method - the TYPO3 shape from phpstan/phpstan#15102, now with the actual package instead of my synthetic wrapper in bug-15102.

robot-loader registers a Nette RobotLoader over a directory Composer does not map, so only that loader can resolve the class (verified: without the bootstrap the project reports 2 errors, and the class has no Composer classmap entry). RobotLoader locks and writes a cache file while resolving, and on 598faaade that fails:

Internal error: Unable to create file '<tmp>/phpstan-e2e-robot-loader/<hash>.php.lock'
  Nette\Loaders\RobotLoader->acquireLock()
  Nette\Loaders\RobotLoader->tryLoad()

because the loader runs while the file-read trap has replaced the file stream wrapper. That is a shape none of the existing projects covered - an autoloader that writes during resolution - and it is the one I would have wanted before touching this code at all. It reproduces 3/3 runs, cold or warm cache, and with or without the explicit setTempDirectory().

Notes

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>
@SanderMuller
SanderMuller force-pushed the e2e-autoloader-shapes branch from 6797a2a to 7132109 Compare August 27, 2026 20:34
@ondrejmirtes
ondrejmirtes merged commit 4f80a48 into phpstan:2.2.x Aug 27, 2026
482 of 483 checks passed
@ondrejmirtes

Copy link
Copy Markdown
Member

Thank you!

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