Skip to content

Commit 3265d5f

Browse files
staabmondrejmirtes
authored andcommitted
Cast non-zero IntegerRangeType toString() is a non-falsy-string
1 parent 66d7701 commit 3265d5f

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

src/Type/IntegerRangeType.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
1010
use PHPStan\Reflection\InitializerExprTypeResolver;
1111
use PHPStan\TrinaryLogic;
12+
use PHPStan\Type\Accessory\AccessoryNonFalsyStringType;
13+
use PHPStan\Type\Accessory\AccessoryNumericStringType;
1214
use PHPStan\Type\Constant\ConstantBooleanType;
1315
use PHPStan\Type\Constant\ConstantIntegerType;
1416
use function array_filter;
@@ -445,6 +447,23 @@ public function toBoolean(): BooleanType
445447
return new ConstantBooleanType(false);
446448
}
447449

450+
public function toString(): Type
451+
{
452+
$isZero = (new ConstantIntegerType(0))->isSuperTypeOf($this);
453+
if ($isZero->no()) {
454+
return new IntersectionType([
455+
new StringType(),
456+
new AccessoryNumericStringType(),
457+
new AccessoryNonFalsyStringType(),
458+
]);
459+
}
460+
461+
return new IntersectionType([
462+
new StringType(),
463+
new AccessoryNumericStringType(),
464+
]);
465+
}
466+
448467
/**
449468
* Return the union with another type, but only if it can be expressed in a simpler way than using UnionType
450469
*

tests/PHPStan/Analyser/nsrt/bug-11129.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public function foo(
5353

5454
assertType('non-empty-string&numeric-string', $i.$bool);
5555
assertType('non-empty-string', $bool.$i);
56-
assertType('non-empty-string&numeric-string', $positiveInt.$bool); // could be 'non-falsy-string&numeric-string'
57-
assertType('non-empty-string&numeric-string', $bool.$positiveInt); // could be 'non-falsy-string&numeric-string'
58-
assertType('non-empty-string&numeric-string', $negativeInt.$bool); // could be 'non-falsy-string&numeric-string'
59-
assertType('non-empty-string', $bool.$negativeInt);
56+
assertType('non-falsy-string&numeric-string', $positiveInt.$bool);
57+
assertType('non-falsy-string&numeric-string', $bool.$positiveInt);
58+
assertType('non-falsy-string&numeric-string', $negativeInt.$bool);
59+
assertType('non-falsy-string', $bool.$negativeInt);
6060

6161
assertType('non-falsy-string', $i.$i);
6262
assertType('non-falsy-string', $negativeInt.$negativeInt);

tests/PHPStan/Analyser/nsrt/cast-to-numeric-string.php

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ function foo(int $a, float $b, $numeric, $numeric2, $number, $positive, $negativ
1818
assertType('numeric-string', (string)$numeric);
1919
assertType('numeric-string', (string)$numeric2);
2020
assertType('numeric-string', (string)$number);
21-
assertType('numeric-string', (string)$positive);
22-
assertType('numeric-string', (string)$negative);
21+
assertType('non-falsy-string&numeric-string', (string)$positive);
22+
assertType('non-falsy-string&numeric-string', (string)$negative);
2323
assertType("'1'", (string)$constantInt);
2424
}
2525

@@ -37,17 +37,17 @@ function concatEmptyString(int $a, float $b, $numeric, $numeric2, $number, $posi
3737
assertType('numeric-string', '' . $numeric);
3838
assertType('numeric-string', '' . $numeric2);
3939
assertType('numeric-string', '' . $number);
40-
assertType('numeric-string', '' . $positive);
41-
assertType('numeric-string', '' . $negative);
40+
assertType('non-falsy-string&numeric-string', '' . $positive);
41+
assertType('non-falsy-string&numeric-string', '' . $negative);
4242
assertType("'1'", '' . $constantInt);
4343

4444
assertType('numeric-string', $a . '');
4545
assertType('numeric-string', $b . '');
4646
assertType('numeric-string', $numeric . '');
4747
assertType('numeric-string', $numeric2 . '');
4848
assertType('numeric-string', $number . '');
49-
assertType('numeric-string', $positive . '');
50-
assertType('numeric-string', $negative . '');
49+
assertType('non-falsy-string&numeric-string', $positive . '');
50+
assertType('non-falsy-string&numeric-string', $negative . '');
5151
assertType("'1'", $constantInt . '');
5252
}
5353

@@ -59,3 +59,20 @@ function concatAssignEmptyString(int $i, float $f) {
5959
$s .= $f;
6060
assertType('numeric-string', $s);
6161
}
62+
63+
/**
64+
* @param int<0, max> $positive
65+
* @param int<min, 0> $negative
66+
*/
67+
function integerRangeToString($positive, $negative)
68+
{
69+
assertType('numeric-string', (string) $positive);
70+
assertType('numeric-string', (string) $negative);
71+
72+
if ($positive !== 0) {
73+
assertType('non-falsy-string&numeric-string', (string) $positive);
74+
}
75+
if ($negative !== 0) {
76+
assertType('non-falsy-string&numeric-string', (string) $negative);
77+
}
78+
}

0 commit comments

Comments
 (0)