diff --git a/src/Analyser/ConstantResolver.php b/src/Analyser/ConstantResolver.php index 846188b985..52dec8da3b 100644 --- a/src/Analyser/ConstantResolver.php +++ b/src/Analyser/ConstantResolver.php @@ -34,6 +34,8 @@ final class ConstantResolver { + public const PHP_MIN_ANALYZABLE_VERSION_ID = 50207; + /** @var array */ private array $currentlyResolving = []; @@ -141,7 +143,7 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type return $this->createInteger($minRelease, $maxRelease); } if ($resolvedConstantName === 'PHP_VERSION_ID') { - $minVersion = 50207; + $minVersion = self::PHP_MIN_ANALYZABLE_VERSION_ID; $maxVersion = null; if ($minPhpVersion !== null) { $minVersion = max($minVersion, $minPhpVersion->getVersionId()); diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index cdb919da1f..051d15d960 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -52,6 +52,7 @@ use PHPStan\Parser\NewAssignedToPropertyVisitor; use PHPStan\Parser\Parser; use PHPStan\Php\PhpVersion; +use PHPStan\Php\PhpVersionFactory; use PHPStan\Php\PhpVersions; use PHPStan\PhpDoc\Tag\TemplateTag; use PHPStan\Reflection\Assertions; @@ -6236,7 +6237,17 @@ public function getIterableValueType(Type $iteratee): Type public function getPhpVersion(): PhpVersions { $constType = $this->getGlobalConstantType(new Name('PHP_VERSION_ID')); - if ($constType !== null) { + + $isOverallPhpVersionRange = false; + if ( + $constType instanceof IntegerRangeType + && $constType->getMin() === ConstantResolver::PHP_MIN_ANALYZABLE_VERSION_ID + && ($constType->getMax() === null || $constType->getMax() === PhpVersionFactory::MAX_PHP_VERSION) + ) { + $isOverallPhpVersionRange = true; + } + + if ($constType !== null && !$isOverallPhpVersionRange) { return new PhpVersions($constType); } diff --git a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php index 1a84e5e170..0c361880e7 100644 --- a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php @@ -586,4 +586,13 @@ public function testBug12951(): void ]); } + public function testNamedArgumentsPhpversion(): void + { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0'); + } + + $this->analyse([__DIR__ . '/data/named-arguments-phpversion.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Classes/data/named-arguments-phpversion.php b/tests/PHPStan/Rules/Classes/data/named-arguments-phpversion.php new file mode 100644 index 0000000000..dbba869398 --- /dev/null +++ b/tests/PHPStan/Rules/Classes/data/named-arguments-phpversion.php @@ -0,0 +1,57 @@ += 8.0 + +declare(strict_types = 1); + +namespace NamedArgumentsPhpversion; + +use Exception; + +class HelloWorld +{ + /** @return mixed[] */ + public function sayHello(): array|null + { + if(PHP_VERSION_ID >= 80400) { + } else { + } + return [ + new Exception(previous: new Exception()), + ]; + } +} + +class HelloWorld2 +{ + /** @return mixed[] */ + public function sayHello(): array|null + { + return [ + PHP_VERSION_ID >= 80400 ? 1 : 0, + new Exception(previous: new Exception()), + ]; + } +} + +class HelloWorld3 +{ + /** @return mixed[] */ + public function sayHello(): array|null + { + return [ + PHP_VERSION_ID >= 70400 ? 1 : 0, + new Exception(previous: new Exception()), + ]; + } +} + +class HelloWorld4 +{ + /** @return mixed[] */ + public function sayHello(): array|null + { + return [ + PHP_VERSION_ID < 80000 ? 1 : 0, + new Exception(previous: new Exception()), + ]; + } +}