From 0c903fc61d1c4c6c963b6c00d286eb88c4e02f66 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 | 22 +++++++++++++++++-- .../Analyser/LooseConstComparisonPhp7Test.php | 1 - .../Analyser/LooseConstComparisonPhp8Test.php | 1 - .../data/loose-const-comparison-php7.php | 1 + .../data/loose-const-comparison-php8.php | 1 + 6 files changed, 28 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..cf323a750d2 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2,6 +2,7 @@ namespace PHPStan\Reflection; +use Hoa\Stream\Test\Unit\IStream\In; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\BinaryOp; @@ -1346,8 +1347,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 +1357,24 @@ public function resolveEqualType(Type $leftType, Type $rightType): BooleanType return new BooleanType(); } + private function looseCompareConstantScalars(ConstantScalarType $leftType, ConstantScalarType $rightType): BooleanType + { + $isNumber = new UnionType([ + new IntegerType(), + new FloatType() + ]); + + if ($leftType->isString()->yes() && $leftType->isNumericString()->no() && $isNumber->isSuperTypeOf($rightType)->yes()) { + return new ConstantBooleanType(!$this->phpVersion->castsNumbersToStringsOnLooseComparison()); + } + if ($rightType->isString()->yes() && $rightType->isNumericString()->no() && $isNumber->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', ]; } diff --git a/tests/PHPStan/Analyser/data/loose-const-comparison-php7.php b/tests/PHPStan/Analyser/data/loose-const-comparison-php7.php index e21ea62d641..76acbb62e08 100644 --- a/tests/PHPStan/Analyser/data/loose-const-comparison-php7.php +++ b/tests/PHPStan/Analyser/data/loose-const-comparison-php7.php @@ -13,4 +13,5 @@ function doFoo() { assertType('true', 42 == "42foo"); assertType('true', 0.0 == ""); + assertType('true', 42.0 == "42foo"); } diff --git a/tests/PHPStan/Analyser/data/loose-const-comparison-php8.php b/tests/PHPStan/Analyser/data/loose-const-comparison-php8.php index a8abbc4a046..f58298b1072 100644 --- a/tests/PHPStan/Analyser/data/loose-const-comparison-php8.php +++ b/tests/PHPStan/Analyser/data/loose-const-comparison-php8.php @@ -13,4 +13,5 @@ function doFoo() { assertType('false', 42 == "42foo"); assertType('false', 0.0 == ""); + assertType('false', 42.0 == "42foo"); }