From e9170077a2e90870a058efc991a739227e5af6e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 03:50:58 +0000 Subject: [PATCH] Fix phpstan/phpstan#13609: Allow numeric-string for %d sprintf placeholder in strict mode - Updated PrintfPlaceholder to accept numeric-string for %d in strict mode, matching existing %f behavior - Added regression test in tests/PHPStan/Rules/Functions/data/bug-13609.php - Updated existing strict test expectations to reflect that numeric-string literals like '1.23' are now accepted for %d --- src/Rules/Functions/PrintfPlaceholder.php | 6 ++++- .../Functions/PrintfParameterTypeRuleTest.php | 15 ++++++++---- .../Rules/Functions/data/bug-13609.php | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 tests/PHPStan/Rules/Functions/data/bug-13609.php diff --git a/src/Rules/Functions/PrintfPlaceholder.php b/src/Rules/Functions/PrintfPlaceholder.php index 28832bd575a..baba0fae7d2 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 placeholder. + 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 1b477cfcbd1..2a7fe8f0613 100644 --- a/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/PrintfParameterTypeRuleTest.php @@ -114,6 +114,17 @@ public function test(): void ]); } + public function testBug13609(): void + { + $this->analyse([__DIR__ . '/data/bug-13609.php'], []); + } + + public function testBug13609Strict(): void + { + $this->checkStrictPrintfPlaceholderTypes = true; + $this->analyse([__DIR__ . '/data/bug-13609.php'], []); + } + public function testStrict(): void { $this->checkStrictPrintfPlaceholderTypes = true; @@ -206,10 +217,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/bug-13609.php b/tests/PHPStan/Rules/Functions/data/bug-13609.php new file mode 100644 index 00000000000..bf36dbc9c84 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-13609.php @@ -0,0 +1,24 @@ +