Skip to content

Commit a58bba7

Browse files
Resolve array~list
1 parent 745ae5a commit a58bba7

File tree

5 files changed

+99
-8
lines changed

5 files changed

+99
-8
lines changed

src/Type/ArrayType.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,10 @@ public function tryRemove(Type $typeToRemove): ?Type
609609
return TypeCombinator::intersect($this, new NonEmptyArrayType());
610610
}
611611

612+
if ($typeToRemove->isSuperTypeOf(new ConstantArrayType([], []))->yes()) {
613+
return TypeCombinator::intersect($this, new NonEmptyArrayType());
614+
}
615+
612616
if ($typeToRemove instanceof NonEmptyArrayType) {
613617
return new ConstantArrayType([], []);
614618
}

stubs/arrayFunctions.stub

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function array_udiff(
7474

7575
/**
7676
* @param array<array-key, mixed> $value
77-
* @return ($value is list ? true : false)
77+
* @return ($value is array{}|non-empty-list ? true : false)
7878
*/
7979
function array_is_list(array $value): bool {}
8080

tests/PHPStan/Analyser/nsrt/array-is-list-type-specifying.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function foo(array $foo) {
88
if (array_is_list($foo)) {
99
assertType('list', $foo);
1010
} else {
11-
assertType('array', $foo);
11+
assertType('non-empty-array', $foo);
1212
}
1313
}
1414

@@ -51,7 +51,7 @@ function foo4(array $foo) {
5151
if (array_is_list($foo)) {
5252
assertType('list', $foo);
5353
} else {
54-
assertType('array<int|string, mixed>', $foo);
54+
assertType('non-empty-array<int|string, mixed>', $foo);
5555
}
5656

5757
$baz = [];

tests/PHPStan/Analyser/nsrt/assert-docblock.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function takesArrayIfTrue(array $arr) : void {
7171
if (validateStringArrayIfTrue($arr)) {
7272
assertType('array<string>', $arr);
7373
} else {
74-
assertType('array<mixed>', $arr);
74+
assertType('non-empty-array<mixed>', $arr);
7575
}
7676
}
7777
/**
@@ -81,7 +81,7 @@ function takesArrayIfTrue1(array $arr) : void {
8181
assertType('array<mixed>', $arr);
8282

8383
if (!validateStringArrayIfTrue($arr)) {
84-
assertType('array<mixed>', $arr);
84+
assertType('non-empty-array<mixed>', $arr);
8585
} else {
8686
assertType('array<string>', $arr);
8787
}
@@ -96,7 +96,7 @@ function takesArrayIfFalse(array $arr) : void {
9696
if (!validateStringArrayIfFalse($arr)) {
9797
assertType('array<string>', $arr);
9898
} else {
99-
assertType('array<mixed>', $arr);
99+
assertType('non-empty-array<mixed>', $arr);
100100
}
101101
}
102102

@@ -107,7 +107,7 @@ function takesArrayIfFalse1(array $arr) : void {
107107
assertType('array<mixed>', $arr);
108108

109109
if (validateStringArrayIfFalse($arr)) {
110-
assertType('array<mixed>', $arr);
110+
assertType('non-empty-array<mixed>', $arr);
111111
} else {
112112
assertType('array<string>', $arr);
113113
}

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

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function doFoo(array $a): void
1717
if (array_is_list($a)) {
1818
assertType('list', $a);
1919
} else {
20-
assertType('array<mixed>', $a); // could be non-empty-array
20+
assertType('non-empty-array<mixed>', $a);
2121
}
2222
}
2323

@@ -45,3 +45,90 @@ public function doFoo3(array $a): void
4545
}
4646

4747
}
48+
49+
class Bar
50+
{
51+
/**
52+
* @param array<array-key, mixed> $value
53+
* @return ($value is non-empty-list ? true : false)
54+
*/
55+
public function assertIsNonEmptyList($value): bool
56+
{
57+
return false;
58+
}
59+
60+
/**
61+
* @param array<array-key, mixed> $value
62+
* @return ($value is list<string> ? true : false)
63+
*/
64+
public function assertIsStringList($value): bool
65+
{
66+
return false;
67+
}
68+
69+
/**
70+
* @param array<array-key, mixed> $value
71+
* @return ($value is list{string, string} ? true : false)
72+
*/
73+
public function assertIsConstantList($value): bool
74+
{
75+
return false;
76+
}
77+
78+
/**
79+
* @param array<array-key, mixed> $value
80+
* @return ($value is list{0?: string, 1?: string} ? true : false)
81+
*/
82+
public function assertIsOptionalConstantList($value): bool
83+
{
84+
return false;
85+
}
86+
87+
/**
88+
* @param array<array-key, mixed> $value
89+
* @return ($value is array<string> ? true : false)
90+
*/
91+
public function assertIsStringArray($value): bool
92+
{
93+
return false;
94+
}
95+
96+
/**
97+
* @param array<mixed> $a
98+
* @return void
99+
*/
100+
public function doFoo(array $a): void
101+
{
102+
if ($this->assertIsNonEmptyList($a)) {
103+
assertType('non-empty-list', $a);
104+
} else {
105+
assertType('array<mixed>', $a);
106+
}
107+
108+
if ($this->assertIsStringList($a)) {
109+
assertType('list<string>', $a);
110+
} else {
111+
assertType('non-empty-array', $a);
112+
}
113+
114+
if ($this->assertIsConstantList($a)) {
115+
assertType('array{string, string}', $a);
116+
} else {
117+
assertType('array', $a);
118+
}
119+
120+
if ($this->assertIsOptionalConstantList($a)) {
121+
assertType('list{0?: string, 1?: string}', $a);
122+
} else {
123+
assertType('non-empty-array', $a);
124+
}
125+
126+
if ($this->assertIsStringArray($a)) {
127+
assertType('array<string>', $a);
128+
} else {
129+
assertType('non-empty-array', $a);
130+
}
131+
}
132+
133+
134+
}

0 commit comments

Comments
 (0)