Skip to content

Commit 3ac64db

Browse files
authored
Fix always-true detection in in_array with union type haystack
1 parent 9d907ae commit 3ac64db

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

src/Rules/Comparison/ImpossibleCheckTypeHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public function findSpecifiedType(
153153
foreach ($haystackArrayTypes as $haystackArrayType) {
154154
if ($haystackArrayType instanceof ConstantArrayType) {
155155
foreach ($haystackArrayType->getValueTypes() as $i => $haystackArrayValueType) {
156-
if ($haystackArrayType->isOptionalKey($i)) {
156+
if (count($haystackArrayValueType->getFiniteTypes()) > 1 || $haystackArrayType->isOptionalKey($i)) {
157157
continue;
158158
}
159159

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,8 +995,16 @@ public function testBug8818(): void
995995

996996
public function testBug12755(): void
997997
{
998+
$tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.';
999+
9981000
$this->treatPhpDocTypesAsCertain = true;
999-
$this->analyse([__DIR__ . '/data/bug-12755.php'], []);
1001+
$this->analyse([__DIR__ . '/data/bug-12755.php'], [
1002+
[
1003+
'Call to function in_array() with arguments null, array{key1: bool|null, key2: null} and true will always evaluate to true.',
1004+
51,
1005+
$tipText,
1006+
],
1007+
]);
10001008
}
10011009

10021010
public function testBug12412(): void

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
namespace Bug12755;
44

5+
class MyEnum
6+
{
7+
public const ONE = 'one';
8+
public const TWO = 'two';
9+
public const THREE = 'three';
10+
}
11+
512
class HelloWorld
613
{
714
/**
@@ -32,4 +39,52 @@ public function testBool(array $myArray): ?\stdClass
3239

3340
return (object) $myArray;
3441
}
42+
43+
/**
44+
* @param array{
45+
* key1: ?bool,
46+
* key2: null,
47+
* } $myArray
48+
*/
49+
public function testNull(array $myArray): ?\stdClass
50+
{
51+
if (\in_array(null, $myArray, true)) {
52+
return null;
53+
}
54+
55+
return (object) $myArray;
56+
}
57+
58+
/**
59+
* @param list<MyEnum::*> $stack
60+
*/
61+
public function testEnum(array $stack): bool
62+
{
63+
return count($stack) === 1 && in_array(MyEnum::ONE, $stack, true);
64+
}
65+
66+
/**
67+
* @param array{1|2|3} $stack
68+
* @param array{1|2|3, 1|2|3} $stack2
69+
* @param array{1|2|3, 2|3} $stack3
70+
* @param array{a?: 1, b: 2|3} $stack4
71+
* @param array{a?: 1} $stack5
72+
*/
73+
public function sayHello(array $stack, array $stack2, array $stack3, array $stack4, array $stack5): void
74+
{
75+
if (in_array(1, $stack, true)) {
76+
}
77+
78+
if (in_array(1, $stack2, true)) {
79+
}
80+
81+
if (in_array(1, $stack3, true)) {
82+
}
83+
84+
if (in_array(1, $stack4, true)) {
85+
}
86+
87+
if (in_array(1, $stack5, true)) {
88+
}
89+
}
3590
}

0 commit comments

Comments
 (0)