Skip to content

Read class-constant @var type without triggering @extends resolution#5502

Merged
phpstan-bot merged 4 commits into2.1.xfrom
fix-14501-flaky-value-of-const
Apr 21, 2026
Merged

Read class-constant @var type without triggering @extends resolution#5502
phpstan-bot merged 4 commits into2.1.xfrom
fix-14501-flaky-value-of-const

Conversation

@ondrejmirtes
Copy link
Copy Markdown
Member

@ondrejmirtes ondrejmirtes commented Apr 21, 2026

Summary

Fixes phpstan/phpstan#14501, a regression introduced in 2.1.48 by #5457. Resolving a class-constant fetch called ClassReflection::getConstant() solely to read getPhpDocType(). That pulls in getAncestors()getParentClass()getFirstExtendsTag(), which eagerly resolves @extends type nodes. When the tag contains value-of<self::CONST>, resolution re-enters constant resolution, hits the currentlyResolvingClassConstant guard, and the MixedType it returns gets cached inside ResolvedPhpDocBlock::$extendsTags. The flakiness the reporter saw is cache-ordering: whichever code path reaches getExtendsTags() first wins, so the error shows up on different classes across runs.

ondrejmirtes and others added 4 commits April 21, 2026 16:24
…CONST>>`

Resolving a class-constant fetch called `ClassReflection::getConstant()`
solely to read `getPhpDocType()`. That pulls in the ancestor walk
(`getAncestors()` → `getParentClass()` → `getFirstExtendsTag()`), which
eagerly resolves `@extends` type nodes. When `@extends` contains
`value-of<self::CONST>`, the resolution re-enters constant resolution,
hits the recursion guard, and the `MixedType` it returns gets baked into
the cached `ResolvedPhpDocBlock::$extendsTags`.

Introduce `ClassReflection::getConstantPhpDocType()`, which reads just
the constant's own `@var` tag without walking ancestors or applying
PHPDoc inheritance. Use it from both `getClassConstFetchTypeByReflection`
call sites. Extract `resolveConstantVarPhpDocType()` to share the @var
tag extraction with `getConstant()`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fixture uses typed class constants (`const string`, `const array`),
which are a PHP 8.3 feature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Describe what it does, not what it resembles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deduplicate the "stub → docComment → fileTypeMapper" fetch shared by
getConstant() and getConstantPhpDocType().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ondrejmirtes ondrejmirtes changed the title Fix phpstan/phpstan#14501: flaky mixed in @extends<value-of<self::CONST>> Read class-constant @var type without triggering @extends resolution Apr 21, 2026
@phpstan-bot phpstan-bot merged commit 1bf9426 into 2.1.x Apr 21, 2026
654 checks passed
@phpstan-bot phpstan-bot deleted the fix-14501-flaky-value-of-const branch April 21, 2026 14:42
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