Skip to content

Fix #8950: define() expressions before use statements breaks class autoloading#4977

Open
phpstan-bot wants to merge 4 commits into2.1.xfrom
create-pull-request/patch-rb6bk20
Open

Fix #8950: define() expressions before use statements breaks class autoloading#4977
phpstan-bot wants to merge 4 commits into2.1.xfrom
create-pull-request/patch-rb6bk20

Conversation

@phpstan-bot
Copy link
Collaborator

@phpstan-bot phpstan-bot commented Feb 17, 2026

Summary

When a define() call (or any expression statement) appeared before use statements in a PHP file, PHPDoc type resolution would fail to resolve class names imported via use. For example, @var FooInterface $foo would resolve to the unqualified FooInterface instead of Some\Namespace\FooInterface.

Changes

  • Removed the !array_key_exists($nameScopeKey, $nameScopeMap) guard in src/Type/FileTypeMapper.php (line 544) so the name scope map entry is always updated with the latest $uses array
  • Added regression test in tests/PHPStan/Analyser/nsrt/bug-8950.php

Root cause

In FileTypeMapper::createPhpDocNodeMap(), the name scope map entry for a given scope key was only set once (guarded by !array_key_exists). The $uses array is populated progressively as use statements are encountered during AST traversal. When a non-skipped statement like define() appeared before use statements, it would create the map entry with an empty $uses array. The guard then prevented any later statement from updating the entry with the correct $uses, causing all subsequent PHPDoc class name resolution in that scope to fail.

The fix removes this guard so that each qualifying statement updates the map entry with the current $uses. Since use statements in PHP are scoped to the entire file/namespace (not position-dependent), the final entry in the map correctly reflects all imports.

Test

The regression test defines an interface in a Bug8950 namespace block, then in a global namespace block places define() before use Bug8950\FooInterface. It verifies that @var FooInterface $foo correctly resolves to Bug8950\FooInterface.

Fixes phpstan/phpstan#8950

Closes phpstan/phpstan#11145
Closes phpstan/phpstan#12639

phpstan-bot and others added 4 commits February 17, 2026 05:09
- Removed !array_key_exists guard in FileTypeMapper::createPhpDocNodeMap() that prevented updating the name scope map entry after it was first set
- The first non-skipped statement (e.g. define()) would lock in an empty $uses array for that scope key, causing later PHPDocs to fail resolving class names from use statements
- New regression test in tests/PHPStan/Analyser/nsrt/bug-8950.php
Closes phpstan/phpstan#11145

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Closes phpstan/phpstan#12639

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automated fix attempt 1 for CI failures.
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.

1 participant