diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index cf7a8b85c9..1376769772 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -17,7 +17,6 @@ use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; -use PHPStan\Type\StringType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; use PHPStan\Type\TypeWithClassName; @@ -82,10 +81,6 @@ public function findSpecifiedType( if (count(TypeUtils::getConstantScalars($argType)) > 0) { return !$argType->toNumber() instanceof ErrorType; } - - if (!(new StringType())->isSuperTypeOf($argType)->no()) { - return null; - } } elseif ($functionName === 'defined') { return null; } elseif ( diff --git a/src/Type/Php/IsNumericFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsNumericFunctionTypeSpecifyingExtension.php index 2810aa711d..4d55395276 100644 --- a/src/Type/Php/IsNumericFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsNumericFunctionTypeSpecifyingExtension.php @@ -34,6 +34,11 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n throw new \PHPStan\ShouldNotHappenException(); } + $argType = $scope->getType($node->args[0]->value); + if (!(new StringType())->isSuperTypeOf($argType)->no()) { + return new SpecifiedTypes([], []); + } + $numericTypes = [ new IntegerType(), new FloatType(), diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index a8d2ad7913..9e9be07432 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -206,6 +206,22 @@ public function testImpossibleCheckTypeFunctionCall(): void 677, 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', ], + [ + 'Call to function is_numeric() with \'123\' will always evaluate to true.', + 692, + ], + [ + 'Call to function is_numeric() with \'blabla\' will always evaluate to false.', + 693, + ], + [ + 'Call to function assert() with true will always evaluate to true.', + 700, + ], + [ + 'Call to function is_numeric() with 123|float will always evaluate to true.', + 700, + ], ] ); } @@ -298,6 +314,10 @@ public function testImpossibleCheckTypeFunctionCallWithoutAlwaysTrue(): void 'Call to function method_exists() with \'CheckTypeFunctionCa…\' and \'unknown\' will always evaluate to false.', 648, ], + [ + 'Call to function is_numeric() with \'blabla\' will always evaluate to false.', + 693, + ], ] ); } diff --git a/tests/PHPStan/Rules/Comparison/data/check-type-function-call.php b/tests/PHPStan/Rules/Comparison/data/check-type-function-call.php index 87a3e102cf..836e63e804 100644 --- a/tests/PHPStan/Rules/Comparison/data/check-type-function-call.php +++ b/tests/PHPStan/Rules/Comparison/data/check-type-function-call.php @@ -682,3 +682,22 @@ public function doFoo($a): bool } } + +class AssertIsNumeric +{ + + public function doFoo(string $str, float $float) + { + assert(is_numeric($str)); + assert(is_numeric('123')); + assert(is_numeric('blabla')); + + $isNumeric = $float; + if (doFoo()) { + $isNumeric = 123; + } + + assert(is_numeric($isNumeric)); + } + +}