Fix #11463: Using phpstan-import-type between classes makes alias unresolvable#4976
Open
phpstan-bot wants to merge 1 commit into2.1.xfrom
Open
Fix #11463: Using phpstan-import-type between classes makes alias unresolvable#4976phpstan-bot wants to merge 1 commit into2.1.xfrom
phpstan-bot wants to merge 1 commit into2.1.xfrom
Conversation
…solvable - When two classes have mutual @phpstan-import-type tags (FooType imports Bar from BarType, BarType imports Foo from FooType), the circular detection in ClassReflection::getTypeAliases() was too aggressive - The fix returns local type aliases (defined via @phpstan-type) when circular import resolution is detected, since local aliases don't depend on imports - Added regression test in tests/PHPStan/Rules/PhpDoc/data/bug-11463.php Closes phpstan/phpstan#11463
staabm
reviewed
Feb 17, 2026
Comment on lines
+1382
to
+1385
| $localAliases = array_map(static fn (TypeAliasTag $typeAliasTag): TypeAlias => $typeAliasTag->getTypeAlias(), $typeAliasTags); | ||
| if ($localAliases !== []) { | ||
| return $localAliases; | ||
| } |
Contributor
There was a problem hiding this comment.
should this assign to $this->typeAliases?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When two classes have mutual
@phpstan-import-typedependencies (e.g.,FooTypeimportsBarfromBarType, andBarTypeimportsFoofromFooType), PHPStan reported "PHPDoc tag @param contains unresolvable type" even though each imported type was a locally-defined@phpstan-typeon the target class.Changes
ClassReflection::getTypeAliases()insrc/Reflection/ClassReflection.phpto return local type aliases (defined via@phpstan-type) when circular import resolution is detected, instead of immediately throwingCircularTypeAliasDefinitionExceptiontests/PHPStan/Rules/PhpDoc/data/bug-11463.phpand corresponding test method inIncompatiblePhpDocTypeRuleTest.phpRoot cause
ClassReflection::getTypeAliases()uses a static$resolvingTypeAliasImportsarray to detect circular import chains. When class A's imports trigger resolution of class B's aliases, which in turn tries to resolve class A's aliases, the method immediately threwCircularTypeAliasDefinitionException. However, this is overly conservative: the imported type is a local@phpstan-typedefinition on the target class, not another import. Local type aliases don't depend on other classes' imports and can be safely returned even during circular resolution.The fix checks whether the class has local type aliases before throwing the exception. If it does, those are returned to break the cycle, allowing the importing class to find the locally-defined type it needs.
Test
The regression test reproduces the exact scenario from the issue: two classes with mutual
@phpstan-import-typetags where each imports a@phpstan-typedefined locally on the other class. The test expects no errors (previously it produced "contains unresolvable type").Fixes phpstan/phpstan#11463