Skip to content

Commit b5638cc

Browse files
phpstan-botclaude
andcommitted
Fix containsNan to handle union array types and optional keys
When a type is a union of constant arrays (e.g. array{NAN}|array{1}), containsNan should only return true if ALL variants contain NAN, not just any of them. Also skip optional keys since absent optional entries mean the array might not actually contain NAN. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 869b3e4 commit b5638cc

2 files changed

Lines changed: 28 additions & 4 deletions

File tree

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,12 +2076,30 @@ private function containsNan(Type $type): bool
20762076
return true;
20772077
}
20782078

2079-
foreach ($type->getConstantArrays() as $constantArray) {
2080-
foreach ($constantArray->getValueTypes() as $valueType) {
2081-
if ($this->containsNan($valueType)) {
2082-
return true;
2079+
$constantArrays = $type->getConstantArrays();
2080+
if ($constantArrays !== [] && $type->isConstantArray()->yes()) {
2081+
foreach ($constantArrays as $constantArray) {
2082+
if (!$this->constantArrayContainsNan($constantArray)) {
2083+
return false;
20832084
}
20842085
}
2086+
2087+
return true;
2088+
}
2089+
2090+
return false;
2091+
}
2092+
2093+
private function constantArrayContainsNan(ConstantArrayType $constantArray): bool
2094+
{
2095+
$optionalKeys = $constantArray->getOptionalKeys();
2096+
foreach ($constantArray->getValueTypes() as $index => $valueType) {
2097+
if (in_array($index, $optionalKeys, true)) {
2098+
continue;
2099+
}
2100+
if ($this->containsNan($valueType)) {
2101+
return true;
2102+
}
20852103
}
20862104

20872105
return false;

tests/PHPStan/Rules/Comparison/data/bug-14394.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ public static function test(float $v1, array $v2): void {
1010
if ($v2 == [NAN]) { echo "never reached\n"; }
1111
if ($v2 === [NAN]) { echo "never reached\n"; }
1212
}
13+
14+
/** @param array{NAN}|array{1} $v */
15+
public static function testUnionArrayNotAlwaysFalse(array $v): void {
16+
if ($v === [1]) { echo "maybe reached\n"; }
17+
if ($v == [1]) { echo "maybe reached\n"; }
18+
}
1319
}

0 commit comments

Comments
 (0)