Skip to content

Commit 0f14aae

Browse files
authored
Support integer ranges in sprintf() constant result inference
1 parent 277cbef commit 0f14aae

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

src/Type/IntegerRangeType.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ public function exponentiate(Type $exponent): Type
616616
return parent::exponentiate($exponent);
617617
}
618618

619+
/**
620+
* @return list<ConstantIntegerType>
621+
*/
619622
public function getFiniteTypes(): array
620623
{
621624
if ($this->min === null || $this->max === null) {

src/Type/Php/SprintfFunctionDynamicReturnTypeExtension.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPStan\Type\Accessory\AccessoryNonFalsyStringType;
1212
use PHPStan\Type\Accessory\AccessoryNumericStringType;
1313
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
14+
use PHPStan\Type\IntegerRangeType;
1415
use PHPStan\Type\IntersectionType;
1516
use PHPStan\Type\StringType;
1617
use PHPStan\Type\Type;
@@ -88,11 +89,20 @@ public function getTypeFromFunctionCall(
8889
$combinationsCount = 1;
8990
foreach ($args as $arg) {
9091
$argType = $scope->getType($arg->value);
91-
if (count($argType->getConstantScalarValues()) === 0) {
92+
$constantScalarValues = $argType->getConstantScalarValues();
93+
94+
if (count($constantScalarValues) === 0) {
95+
if ($argType instanceof IntegerRangeType) {
96+
foreach ($argType->getFiniteTypes() as $finiteType) {
97+
$constantScalarValues[] = $finiteType->getValue();
98+
}
99+
}
100+
}
101+
102+
if (count($constantScalarValues) === 0) {
92103
return $returnType;
93104
}
94105

95-
$constantScalarValues = $argType->getConstantScalarValues();
96106
$values[] = $constantScalarValues;
97107
$combinationsCount *= count($constantScalarValues);
98108
}

tests/PHPStan/Analyser/data/dynamic-sprintf.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,22 @@ public function doFoo(string $a, string $b, string $c): void
1818
assertType("'a b c'|'a b cc'|'a bb c'|'a bb cc'|'aa b c'|'aa b cc'|'aa bb c'|'aa bb cc'", sprintf('%s %s %s', $a, $b, $c));
1919
}
2020

21+
/**
22+
* @param int<0,3> $a
23+
* @param 'b'|'bb' $b
24+
*/
25+
public function integerRange(int $a, string $b): void
26+
{
27+
assertType("'0 b'|'0 bb'|'1 b'|'1 bb'|'2 b'|'2 bb'|'3 b'|'3 bb'", sprintf('%d %s', $a, $b));
28+
}
29+
30+
/**
31+
* @param int<0,64> $a
32+
* @param 'b'|'bb' $b
33+
*/
34+
public function tooBigRange(int $a, string $b): void
35+
{
36+
assertType("non-falsy-string", sprintf('%d %s', $a, $b));
37+
}
38+
2139
}

0 commit comments

Comments
 (0)