From 81386b6e076a3388df69baf60d7379ed4fb5285c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 5 Feb 2023 12:07:57 +0100 Subject: [PATCH] Fix --- src/Php/PhpVersion.php | 6 ++++++ .../InitializerExprTypeResolver.php | 21 +++++++++++++++++-- .../Analyser/LooseConstComparisonPhp7Test.php | 1 - .../Analyser/LooseConstComparisonPhp8Test.php | 1 - 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index f6afda248a1..dbc131b1e89 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -216,4 +216,10 @@ public function arrayFunctionsReturnNullWithNonArray(): bool return $this->versionId < 80000; } + // see https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.core.string-number-comparision + public function castsNumbersToStringsOnLooseComparison(): bool + { + return $this->versionId >= 80000; + } + } diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index ee5a49a8228..cd7be87226f 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -1346,8 +1346,7 @@ public function resolveEqualType(Type $leftType, Type $rightType): BooleanType } if ($leftType instanceof ConstantScalarType && $rightType instanceof ConstantScalarType) { - // @phpstan-ignore-next-line - return new ConstantBooleanType($leftType->getValue() == $rightType->getValue()); // phpcs:ignore + return $this->looseCompareConstantScalars($leftType, $rightType); } if ($leftType instanceof ConstantArrayType && $rightType instanceof ConstantArrayType) { @@ -1357,6 +1356,24 @@ public function resolveEqualType(Type $leftType, Type $rightType): BooleanType return new BooleanType(); } + private function looseCompareConstantScalars(ConstantScalarType $leftType, ConstantScalarType $rightType): BooleanType + { + $isZero = new UnionType([ + new ConstantIntegerType(0), + new ConstantFloatType(0.0), + ]); + + if ($leftType->isString()->yes() && $leftType->isNumericString()->no() && $isZero->isSuperTypeOf($rightType)->yes()) { + return new ConstantBooleanType(!$this->phpVersion->castsNumbersToStringsOnLooseComparison()); + } + if ($rightType->isString()->yes() && $rightType->isNumericString()->no() && $isZero->isSuperTypeOf($leftType)->yes()) { + return new ConstantBooleanType(!$this->phpVersion->castsNumbersToStringsOnLooseComparison()); + } + + // @phpstan-ignore-next-line + return new ConstantBooleanType($leftType->getValue() == $rightType->getValue()); // phpcs:ignore + } + /** * @param callable(Type, Type): BooleanType $valueComparisonCallback */ diff --git a/tests/PHPStan/Analyser/LooseConstComparisonPhp7Test.php b/tests/PHPStan/Analyser/LooseConstComparisonPhp7Test.php index 303363bfe41..22548646a9a 100644 --- a/tests/PHPStan/Analyser/LooseConstComparisonPhp7Test.php +++ b/tests/PHPStan/Analyser/LooseConstComparisonPhp7Test.php @@ -31,7 +31,6 @@ public function testFileAsserts( public static function getAdditionalConfigFiles(): array { return [ - __DIR__ . '/../../../conf/bleedingEdge.neon', __DIR__ . '/looseConstComparisonPhp7.neon', ]; } diff --git a/tests/PHPStan/Analyser/LooseConstComparisonPhp8Test.php b/tests/PHPStan/Analyser/LooseConstComparisonPhp8Test.php index f91b6aa6a84..28f57243af8 100644 --- a/tests/PHPStan/Analyser/LooseConstComparisonPhp8Test.php +++ b/tests/PHPStan/Analyser/LooseConstComparisonPhp8Test.php @@ -31,7 +31,6 @@ public function testFileAsserts( public static function getAdditionalConfigFiles(): array { return [ - __DIR__ . '/../../../conf/bleedingEdge.neon', __DIR__ . '/looseConstComparisonPhp8.neon', ]; }