From f173f43e2ba40a654816dc367fb9a7aa3184c6d5 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Thu, 12 Feb 2026 08:46:11 +0000 Subject: [PATCH] Fix #13609 --- src/Rules/Functions/PrintfPlaceholder.php | 6 +++++- .../Rules/Functions/PrintfParameterTypeRuleTest.php | 4 ---- .../PHPStan/Rules/Functions/data/printf-param-types.php | 9 +++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Rules/Functions/PrintfPlaceholder.php b/src/Rules/Functions/PrintfPlaceholder.php index 28832bd575..1a776ddb53 100644 --- a/src/Rules/Functions/PrintfPlaceholder.php +++ b/src/Rules/Functions/PrintfPlaceholder.php @@ -34,7 +34,11 @@ public function doesArgumentTypeMatchPlaceholder(Type $argumentType, bool $stric return (new IntegerType())->accepts($argumentType, true)->yes(); case 'int': return $strictPlaceholderTypes - ? (new IntegerType())->accepts($argumentType, true)->yes() + ? (new UnionType([ + new IntegerType(), + // numeric-string is allowed for consistency with the float case and phpstan-strict-rules. + new IntersectionType([new StringType(), new AccessoryNumericStringType()]), + ]))->accepts($argumentType, true)->yes() : ! $argumentType->toInteger() instanceof ErrorType; case 'float': return $strictPlaceholderTypes diff --git a/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php b/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php index 835700921c..c5c720cb05 100644 --- a/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php @@ -206,10 +206,6 @@ public function testStrict(): void 'Parameter #2 of function printf is expected to be int by placeholder #1 ("%d"), string given.', 36, ], - [ - 'Parameter #2 of function printf is expected to be int by placeholder #1 ("%d"), string given.', - 37, - ], [ 'Parameter #2 of function printf is expected to be int by placeholder #1 ("%d"), null given.', 38, diff --git a/tests/PHPStan/Rules/Functions/data/printf-param-types.php b/tests/PHPStan/Rules/Functions/data/printf-param-types.php index f3c54c77d7..52ca882e7e 100644 --- a/tests/PHPStan/Rules/Functions/data/printf-param-types.php +++ b/tests/PHPStan/Rules/Functions/data/printf-param-types.php @@ -70,3 +70,12 @@ public function __toString(): string printf('%s %2$*s', 'a', 5, 'a'); printf('%1$-+\'X10.2f', 5); printf('%1$*.*f %s %2$d', 5, 6, new FooStringable()); // 5.000000 foo 6 + +// Bug #13609 - numeric-string should be accepted by %d placeholder +/** @param numeric-string $numericStr */ +function testNumericStringWithIntPlaceholder(string $numericStr): void { + printf('%d', $numericStr); + printf('%04d-%02d-%02d', $numericStr, $numericStr, $numericStr); + sprintf('%d', $numericStr); + printf('%f', $numericStr); +}