From eeced6091cc357ef7e879e03edf9098eda916d2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 28 Feb 2026 14:44:26 +0000 Subject: [PATCH] Fix false positive for trait array constants using class constants as 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 https://github.com/phpstan/phpstan/issues/11351 --- .../Traits/ConflictingTraitConstantsRule.php | 5 +-- .../ConflictingTraitConstantsRuleTest.php | 6 +++ tests/PHPStan/Rules/Traits/data/bug-11351.php | 41 +++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Rules/Traits/data/bug-11351.php diff --git a/src/Rules/Traits/ConflictingTraitConstantsRule.php b/src/Rules/Traits/ConflictingTraitConstantsRule.php index 7176adb2f0..2c760eede4 100644 --- a/src/Rules/Traits/ConflictingTraitConstantsRule.php +++ b/src/Rules/Traits/ConflictingTraitConstantsRule.php @@ -80,10 +80,7 @@ public function processNode(Node $node, Scope $scope): array $classConstantValueType = $this->initializerExprTypeResolver->getType($const->value, InitializerExprContext::fromClassReflection($classReflection)); $traitConstantValueType = $this->initializerExprTypeResolver->getType( $immediateTraitConstant->getValueExpression(), - InitializerExprContext::fromClass( - $immediateTraitConstant->getDeclaringClass()->getName(), - $immediateTraitConstant->getDeclaringClass()->getFileName() !== false ? $immediateTraitConstant->getDeclaringClass()->getFileName() : null, - ), + InitializerExprContext::fromClassReflection($classReflection), ); if ($classConstantValueType->equals($traitConstantValueType)) { continue; diff --git a/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php b/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php index 5acfbf3229..62c23b88dc 100644 --- a/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php +++ b/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php @@ -85,4 +85,10 @@ public function testBug13119(): void $this->analyse([__DIR__ . '/data/bug-13119.php'], []); } + #[RequiresPhp('>= 8.3')] + public function testBug11351(): void + { + $this->analyse([__DIR__ . '/data/bug-11351.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Traits/data/bug-11351.php b/tests/PHPStan/Rules/Traits/data/bug-11351.php new file mode 100644 index 0000000000..601db00d0b --- /dev/null +++ b/tests/PHPStan/Rules/Traits/data/bug-11351.php @@ -0,0 +1,41 @@ += 8.2 + +declare(strict_types = 1); + +namespace Bug11351; + +trait TA +{ + protected const array A = [ + self::CA => 'CA', + ]; +} + +class A +{ + use TA; + + public const CA = 'abc'; + + protected const array A = [ + self::CA => 'CA', + ]; +} + +trait TB +{ + protected const array B = [ + 'key' => self::CB, + ]; +} + +class B +{ + use TB; + + public const CB = 'xyz'; + + protected const array B = [ + 'key' => self::CB, + ]; +}