diff --git a/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php b/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php index 04daf2ed55..cab2d7d007 100644 --- a/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php @@ -12,7 +12,7 @@ use PHPStan\DependencyInjection\AutowiredService; use PHPStan\Reflection\FunctionReflection; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\Accessory\AccessoryNumericStringType; +use PHPStan\Type\Accessory\AccessoryDecimalIntegerStringType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\FunctionTypeSpecifyingExtension; use PHPStan\Type\IntegerRangeType; @@ -56,7 +56,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n if ($context->true()) { $types[] = new IntersectionType([ new StringType(), - new AccessoryNumericStringType(), + new AccessoryDecimalIntegerStringType(), ]); } @@ -68,7 +68,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n IntegerRangeType::fromInterval(0, null), new IntersectionType([ new StringType(), - new AccessoryNumericStringType(), + new AccessoryDecimalIntegerStringType(), ]), new ConstantBooleanType(true), ]); diff --git a/tests/PHPStan/Analyser/nsrt/callsite-cast-narrowing.php b/tests/PHPStan/Analyser/nsrt/callsite-cast-narrowing.php index 239e49d53a..9dc8c72067 100644 --- a/tests/PHPStan/Analyser/nsrt/callsite-cast-narrowing.php +++ b/tests/PHPStan/Analyser/nsrt/callsite-cast-narrowing.php @@ -13,7 +13,7 @@ class HelloWorld public function sayHello($mixed, int $int, string $string, $numericString, $nonEmptyString, bool $bool): void { if (ctype_digit((string) $mixed)) { - assertType('int<0, max>|numeric-string|true', $mixed); + assertType('int<0, max>|decimal-int-string|true', $mixed); } else { assertType('mixed~(int<0, max>|numeric-string|true)', $mixed); } @@ -41,7 +41,7 @@ public function sayHello($mixed, int $int, string $string, $numericString, $nonE assertType('int', $int); if (ctype_digit((string) $string)) { - assertType('numeric-string', $string); + assertType('decimal-int-string', $string); } else { assertType('string', $string); } @@ -54,10 +54,11 @@ public function sayHello($mixed, int $int, string $string, $numericString, $nonE } assertType('string', $string); + // see https://3v4l.org/1Qrlg#veol if (ctype_digit((string) $numericString)) { - assertType('numeric-string', $numericString); + assertType('decimal-int-string', $numericString); } else { - assertType('*NEVER*', $numericString); + assertType('numeric-string', $numericString); } assertType('numeric-string', $numericString); diff --git a/tests/PHPStan/Analyser/nsrt/ctype-digit.php b/tests/PHPStan/Analyser/nsrt/ctype-digit.php index ed4704daa7..ec496e6fbe 100644 --- a/tests/PHPStan/Analyser/nsrt/ctype-digit.php +++ b/tests/PHPStan/Analyser/nsrt/ctype-digit.php @@ -14,7 +14,7 @@ public function foo(mixed $foo): void assertType('mixed', $foo); if (is_string($foo) && ctype_digit($foo)) { - assertType('numeric-string', $foo); + assertType('decimal-int-string', $foo); } else { assertType('mixed', $foo); } @@ -26,7 +26,7 @@ public function foo(mixed $foo): void } if (ctype_digit($foo)) { - assertType('int<48, 57>|int<256, max>|numeric-string', $foo); + assertType('int<48, 57>|int<256, max>|decimal-int-string', $foo); return; } diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 9ea18aac9b..ccfe81ca98 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -5158,6 +5158,30 @@ public static function dataRemove(): array UnionType::class, 'array|ArrayObject', ], + [ + new IntersectionType([ + new StringType(), + new AccessoryNumericStringType(), + ]), + new IntersectionType([ + new StringType(), + new AccessoryDecimalIntegerStringType(), + ]), + IntersectionType::class, + 'numeric-string' + ], + [ + new IntersectionType([ + new StringType(), + new AccessoryDecimalIntegerStringType(), + ]), + new IntersectionType([ + new StringType(), + new AccessoryNumericStringType(), + ]), + NeverType::class, + '*NEVER*=implicit' + ], [ new ConstantBooleanType(true), new ConstantBooleanType(false),