Add regression test for circular class constant PHPDoc type references#5685
Open
phpstan-bot wants to merge 3 commits into
Open
Add regression test for circular class constant PHPDoc type references#5685phpstan-bot wants to merge 3 commits into
phpstan-bot wants to merge 3 commits into
Conversation
- Add nsrt test verifying correct type resolution when class constant PHPDoc types cross-reference each other (e.g. int<0, self::MAX> and int<self::MIN, max>) - Add integration test proving the code completes without hanging, covering both the non-circular value case (literals) and the circular value case (which reports unresolvable type errors) - The underlying hang was fixed by the currentlyResolvingClassConstant guard in InitializerExprTypeResolver (commit 93af41b), but no regression test existed for the specific scenario from issue #9172 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test just needs to verify PHPStan doesn't hang on circular class constant PHPDoc references — asserting specific error messages is unnecessary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The integration test alone is sufficient to verify PHPStan doesn't hang on circular class constant PHPDoc type references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
VincentLanglet
approved these changes
May 16, 2026
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
Issue #9172 reported that circular PHPDoc type annotations on class constants (e.g.,
@var int<0, self::MAX_DEPOSIT>on MIN_DEPOSIT and@var int<self::MIN_DEPOSIT, max>on MAX_DEPOSIT) caused PHPStan to hang indefinitely. The underlying hang was already fixed by thecurrentlyResolvingClassConstantcycle detection guard inInitializerExprTypeResolver(commit 93af41b), but no regression test existed for the specific scenario described in the issue.Changes
tests/PHPStan/Analyser/nsrt/bug-9172.php— type assertion test verifying:static::access (int<0, 20000> and int<1000, max>)@paramtype annotations resolves correctly (int<1000, 20000>)tests/PHPStan/Analyser/data/bug-9172.php— integration test data file with:testBug9172()intests/PHPStan/Analyser/AnalyserIntegrationTest.phpverifying:Root cause
The original hang occurred because
InitializerExprTypeResolver::getClassConstFetchTypeByReflection()had no protection against circular class constant resolution. This was fixed in commit 93af41b by adding a$currentlyResolvingClassConstanttracking array that returnsMixedType()when a cycle is detected.For the specific case in issue #9172 (literal values with cross-referencing PHPDoc annotations), the resolution actually works without triggering the cycle guard because
TypeNodeResolver::resolveConstTypeNode()resolves constants by reading their VALUE expressions (not their declared types), soself::MAX_DEPOSITresolves to the literal20000andself::MIN_DEPOSITresolves to1000— no recursion needed.Test
tests/PHPStan/Analyser/nsrt/bug-9172.php— asserts correct type inference for the cross-referencing constant typestests/PHPStan/Analyser/data/bug-9172.phpwithtestBug9172()— integration test proving no hang occursAnalogous cases probed and found to be already correct:
ConstantResolver::$currentlyResolving)UsefulTypeAliasResolver::$inProcess)$currentlyResolvingClassConstantguard, tested in bug-10147)Fixes phpstan/phpstan#9172