Fix #11351: Defining Array Constants in PHP Traits Causes Errors When Using Class Constants as Keys or Values#5101
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
… keys/values - Trait constant values were resolved in the trait's own context, causing self:: references to class constants to be unresolvable - Changed ConflictingTraitConstantsRule to evaluate trait constant values in the using class context, since self in a trait resolves to the using class - New regression test in tests/PHPStan/Rules/Traits/data/bug-11351.php Closes phpstan/phpstan#11351
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 a trait defines an array constant that uses
self::CONSTas a key or value, PHPStan incorrectly reported "overriding constant with different value" because it resolved the trait constant's value expression in the trait's own context (where the class constant doesn't exist), rather than in the using class's context (whereselfactually resolves at runtime).Changes
src/Rules/Traits/ConflictingTraitConstantsRule.php: Changed theInitializerExprContextused to evaluate the trait constant value fromInitializerExprContext::fromClass(traitName, ...)toInitializerExprContext::fromClassReflection($classReflection), so thatself::references in trait constants are resolved in the using class's context.Root cause
In
ConflictingTraitConstantsRule, when comparing a class constant value against the trait constant value it overrides, the trait constant's value expression was evaluated usingInitializerExprContext::fromClass()with the trait's class name. This meantself::CAin the trait couldn't findCA(defined in the using class), producing a genericnon-empty-array<int|string, 'CA'>type instead of the specificarray{abc: 'CA'}. The fix evaluates the trait constant in the using class's context, matching PHP's actualselfresolution semantics in traits.Test
Added
tests/PHPStan/Rules/Traits/data/bug-11351.phpwith two test cases:self::CAas an array keyself::CBas an array valueBoth expect no errors (the previous false positives are eliminated).
Fixes phpstan/phpstan#11351