diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index a84eacfa9d..3e76a98ef8 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1992,7 +1992,18 @@ private function resolveType(Expr $node): Type return new MixedType(); } - $constantType = $constantReflection->getValueType(); + if ( + $isObject + && ( + !$constantReflection instanceof ClassConstantReflection + || !$constantClassReflection->isFinal() + ) + ) { + $constantType = $constantReflection->getValueType(); + } else { + $constantType = ConstantTypeHelper::getTypeFromValue($constantReflection->getValue()); + } + if ( $constantType instanceof ConstantType && in_array(sprintf('%s::%s', $constantClassReflection->getName(), $constantName), $this->dynamicConstantNames, true) diff --git a/tests/PHPStan/Analyser/data/bug-5293.php b/tests/PHPStan/Analyser/data/bug-5293.php index 63f30fe000..40d8ca8cc4 100644 --- a/tests/PHPStan/Analyser/data/bug-5293.php +++ b/tests/PHPStan/Analyser/data/bug-5293.php @@ -49,7 +49,7 @@ public static function getAllSupportedCurrencies(): void { array_map( function (string $currencyCode): int { - assertType('non-empty-string', $currencyCode); + assertType('\'AUD\'|\'BGN\'|\'BRL\'|\'CAD\'|\'CHF\'|\'CZK\'|\'DKK\'|\'EUR\'|\'GBP\'|\'HUF\'|\'NOK\'|\'NZD\'|\'PLN\'|\'RON\'|\'SEK\'|\'SGD\'|\'USD\'', $currencyCode); return 1; }, self::SUPPORTED_CURRENCIES diff --git a/tests/PHPStan/Analyser/data/class-constant-stub-files.php b/tests/PHPStan/Analyser/data/class-constant-stub-files.php index 93f25365f3..4777b0ec22 100644 --- a/tests/PHPStan/Analyser/data/class-constant-stub-files.php +++ b/tests/PHPStan/Analyser/data/class-constant-stub-files.php @@ -15,6 +15,10 @@ class Foo } function (): void { - assertType('int', Foo::BAR); - assertType('int', Foo::BAZ); + assertType('1', Foo::BAR); + assertType('1', Foo::BAZ); + + $foo = new Foo(); + assertType('int', $foo::BAR); + assertType('int', $foo::BAZ); }; diff --git a/tests/PHPStan/Analyser/data/class-constant-types.php b/tests/PHPStan/Analyser/data/class-constant-types.php index c5fd3499b2..9d60af25c5 100644 --- a/tests/PHPStan/Analyser/data/class-constant-types.php +++ b/tests/PHPStan/Analyser/data/class-constant-types.php @@ -21,11 +21,11 @@ public function doFoo() assertType('mixed', static::NO_TYPE); assertType('mixed', $this::NO_TYPE); - assertType('string', self::TYPE); + assertType('\'foo\'', self::TYPE); assertType('string', static::TYPE); assertType('string', $this::TYPE); - assertType('string', self::PRIVATE_TYPE); + assertType('\'foo\'', self::PRIVATE_TYPE); assertType('string', static::PRIVATE_TYPE); assertType('string', $this::PRIVATE_TYPE); } @@ -41,7 +41,7 @@ class Bar extends Foo public function doFoo() { - assertType('string', self::TYPE); + assertType('\'bar\'', self::TYPE); assertType('string', static::TYPE); assertType('string', $this::TYPE); @@ -60,7 +60,7 @@ class Baz extends Foo public function doFoo() { - assertType('int', self::TYPE); + assertType('1', self::TYPE); assertType('int', static::TYPE); assertType('int', $this::TYPE); } @@ -75,9 +75,37 @@ class Lorem extends Foo public function doFoo() { - assertType('string', self::TYPE); + assertType('1', self::TYPE); assertType('string', static::TYPE); assertType('string', $this::TYPE); } } + +final class FinalFoo +{ + + const NO_TYPE = 1; + + /** @var string */ + const TYPE = 'foo'; + + /** @var string */ + private const PRIVATE_TYPE = 'foo'; + + public function doFoo() + { + assertType('1', self::NO_TYPE); + assertType('1', static::NO_TYPE); + assertType('1', $this::NO_TYPE); + + assertType('\'foo\'', self::TYPE); + assertType('\'foo\'', static::TYPE); + assertType('\'foo\'', $this::TYPE); + + assertType('\'foo\'', self::PRIVATE_TYPE); + assertType('\'foo\'', static::PRIVATE_TYPE); + assertType('\'foo\'', $this::PRIVATE_TYPE); + } + +}