Skip to content

Commit

Permalink
Cast non-zero IntegerRangeType toString() is a non-falsy-string
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored and ondrejmirtes committed Jun 19, 2024
1 parent 66d7701 commit 3265d5f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 10 deletions.
19 changes: 19 additions & 0 deletions src/Type/IntegerRangeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Reflection\InitializerExprTypeResolver;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\AccessoryNonFalsyStringType;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Constant\ConstantIntegerType;
use function array_filter;
Expand Down Expand Up @@ -445,6 +447,23 @@ public function toBoolean(): BooleanType
return new ConstantBooleanType(false);
}

public function toString(): Type
{
$isZero = (new ConstantIntegerType(0))->isSuperTypeOf($this);
if ($isZero->no()) {
return new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
new AccessoryNonFalsyStringType(),
]);
}

return new IntersectionType([
new StringType(),
new AccessoryNumericStringType(),
]);
}

/**
* Return the union with another type, but only if it can be expressed in a simpler way than using UnionType
*
Expand Down
8 changes: 4 additions & 4 deletions tests/PHPStan/Analyser/nsrt/bug-11129.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ public function foo(

assertType('non-empty-string&numeric-string', $i.$bool);
assertType('non-empty-string', $bool.$i);
assertType('non-empty-string&numeric-string', $positiveInt.$bool); // could be 'non-falsy-string&numeric-string'
assertType('non-empty-string&numeric-string', $bool.$positiveInt); // could be 'non-falsy-string&numeric-string'
assertType('non-empty-string&numeric-string', $negativeInt.$bool); // could be 'non-falsy-string&numeric-string'
assertType('non-empty-string', $bool.$negativeInt);
assertType('non-falsy-string&numeric-string', $positiveInt.$bool);
assertType('non-falsy-string&numeric-string', $bool.$positiveInt);
assertType('non-falsy-string&numeric-string', $negativeInt.$bool);
assertType('non-falsy-string', $bool.$negativeInt);

assertType('non-falsy-string', $i.$i);
assertType('non-falsy-string', $negativeInt.$negativeInt);
Expand Down
29 changes: 23 additions & 6 deletions tests/PHPStan/Analyser/nsrt/cast-to-numeric-string.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ function foo(int $a, float $b, $numeric, $numeric2, $number, $positive, $negativ
assertType('numeric-string', (string)$numeric);
assertType('numeric-string', (string)$numeric2);
assertType('numeric-string', (string)$number);
assertType('numeric-string', (string)$positive);
assertType('numeric-string', (string)$negative);
assertType('non-falsy-string&numeric-string', (string)$positive);
assertType('non-falsy-string&numeric-string', (string)$negative);
assertType("'1'", (string)$constantInt);
}

Expand All @@ -37,17 +37,17 @@ function concatEmptyString(int $a, float $b, $numeric, $numeric2, $number, $posi
assertType('numeric-string', '' . $numeric);
assertType('numeric-string', '' . $numeric2);
assertType('numeric-string', '' . $number);
assertType('numeric-string', '' . $positive);
assertType('numeric-string', '' . $negative);
assertType('non-falsy-string&numeric-string', '' . $positive);
assertType('non-falsy-string&numeric-string', '' . $negative);
assertType("'1'", '' . $constantInt);

assertType('numeric-string', $a . '');
assertType('numeric-string', $b . '');
assertType('numeric-string', $numeric . '');
assertType('numeric-string', $numeric2 . '');
assertType('numeric-string', $number . '');
assertType('numeric-string', $positive . '');
assertType('numeric-string', $negative . '');
assertType('non-falsy-string&numeric-string', $positive . '');
assertType('non-falsy-string&numeric-string', $negative . '');
assertType("'1'", $constantInt . '');
}

Expand All @@ -59,3 +59,20 @@ function concatAssignEmptyString(int $i, float $f) {
$s .= $f;
assertType('numeric-string', $s);
}

/**
* @param int<0, max> $positive
* @param int<min, 0> $negative
*/
function integerRangeToString($positive, $negative)
{
assertType('numeric-string', (string) $positive);
assertType('numeric-string', (string) $negative);

if ($positive !== 0) {
assertType('non-falsy-string&numeric-string', (string) $positive);
}
if ($negative !== 0) {
assertType('non-falsy-string&numeric-string', (string) $negative);
}
}

0 comments on commit 3265d5f

Please sign in to comment.