Skip to content

Commit

Permalink
fix '0' and '1'
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Sep 20, 2024
1 parent 612c082 commit 7cfeacd
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 14 deletions.
34 changes: 30 additions & 4 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -823,10 +823,36 @@ public function specifyTypesInCondition(
if (!$varType->isIterableAtLeastOnce()->no()) {
$varIterableKeyType = $varType->getIterableKeyType();

if ($varIterableKeyType->isString()->yes()
&& $varIterableKeyType->isNumericString()->no()
) {
if (!$varIterableKeyType->isNonEmptyString()->no()) {
if ($varIterableKeyType->isConstantScalarValue()->yes()) {
$varIterableKeyType = TypeCombinator::union(
$varIterableKeyType,
TypeCombinator::remove($varIterableKeyType->toString(), new ConstantStringType('')),
$varIterableKeyType->toFloat(),
);

$zero = new UnionType([
new ConstantStringType('0'),
new ConstantIntegerType(0),
]);
if (!$varIterableKeyType->isSuperTypeOf($zero)->no()) {
$varIterableKeyType = TypeCombinator::union(
$varIterableKeyType,
new ConstantBooleanType(false)
);
}

$one = new UnionType([
new ConstantStringType('1'),
new ConstantIntegerType(1),
]);
if (!$varIterableKeyType->isSuperTypeOf($one)->no()) {
$varIterableKeyType = TypeCombinator::union(
$varIterableKeyType,
new ConstantBooleanType(true)
);
}

if (!$varIterableKeyType->isSuperTypeOf(new ConstantStringType(''))->no()) {
$varIterableKeyType = TypeCombinator::addNull($varIterableKeyType);
}

Expand Down
49 changes: 39 additions & 10 deletions tests/PHPStan/Analyser/nsrt/bug-11716.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ public function parse(string $glue): string

/**
* @param array<int, string> $arr
* @param array<1|'2', string> $numericKeyArray
*/
function narrowKey($mixed, string $s, int $i, array $generalArr, array $arr, array $numericKeyArray): void {
function narrowKey($mixed, string $s, int $i, array $generalArr, array $arr): void {
if (isset($generalArr[$mixed])) {
assertType('mixed~array|object|resource', $mixed);
} else {
Expand Down Expand Up @@ -80,13 +79,6 @@ function narrowKey($mixed, string $s, int $i, array $generalArr, array $arr, arr
assertType('string', $s);
}
assertType('string', $s);

if (isset($numericKeyArray[$mixed])) {
assertType("mixed~array|object|resource", $mixed);
} else {
assertType("mixed", $mixed);
}
assertType("mixed", $mixed);
}

/**
Expand Down Expand Up @@ -141,9 +133,46 @@ function emptyString($mixed)
{
// see https://3v4l.org/XHZdr
$arr = ['' => 1, 'a' => 2];
if (isset($arr[$mixed])) {
assertType("0.0|''|'a'|null", $mixed); // could be ''|'a'|null
} else {
assertType('mixed', $mixed);
}
assertType('mixed', $mixed);
}

function numericString($mixed)
{
$arr = ['1' => 1, '2' => 2];
if (isset($arr[$mixed])) {
assertType("1|1.0|2|2.0|'1'|'2'|true", $mixed);
} else {
assertType('mixed', $mixed);
}
assertType('mixed', $mixed);

$arr = ['0' => 1, '2' => 2];
if (isset($arr[$mixed])) {
assertType("0|0.0|2|2.0|'0'|'2'|false", $mixed);
} else {
assertType('mixed', $mixed);
}
assertType('mixed', $mixed);
}

function intKeys($mixed)
{
$arr = [1 => 1, 2 => 2];
if (isset($arr[$mixed])) {
assertType("1|1.0|2|2.0|'1'|'2'|true", $mixed);
} else {
assertType('mixed', $mixed);
}
assertType('mixed', $mixed);

$arr = [0 => 0, 1 => 1, 2 => 2];
if (isset($arr[$mixed])) {
assertType("''|'a'|null", $mixed);
assertType("0|0.0|1|1.0|2|2.0|'0'|'1'|'2'|bool", $mixed);
} else {
assertType('mixed', $mixed);
}
Expand Down

0 comments on commit 7cfeacd

Please sign in to comment.