Skip to content

Commit 0977a7b

Browse files
committed
Constant arrays should be preserved after sorting, just not as certain lists
1 parent ad34452 commit 0977a7b

File tree

4 files changed

+48
-11
lines changed

4 files changed

+48
-11
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,6 +3207,22 @@ private function getArraySortDoNotPreserveListFunctionType(Type $type): Type
32073207
return $traverse($type);
32083208
}
32093209

3210+
$constantArrays = $type->getConstantArrays();
3211+
if (count($constantArrays) > 0) {
3212+
$types = [];
3213+
foreach ($constantArrays as $constantArray) {
3214+
$types[] = new ConstantArrayType(
3215+
$constantArray->getKeyTypes(),
3216+
$constantArray->getValueTypes(),
3217+
$constantArray->getNextAutoIndexes(),
3218+
$constantArray->getOptionalKeys(),
3219+
TrinaryLogic::createMaybe(),
3220+
);
3221+
}
3222+
3223+
return TypeCombinator::union(...$types);
3224+
}
3225+
32103226
$newArrayType = new ArrayType($type->getIterableKeyType(), $type->getIterableValueType());
32113227
if ($isIterableAtLeastOnce->yes()) {
32123228
$newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType());

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,10 @@ public function dataFileAsserts(): iterable
654654
}
655655

656656
yield from $this->gatherAssertTypes(__DIR__ . '/data/never.php');
657-
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10627.php');
657+
658+
if (PHP_VERSION_ID >= 80100) {
659+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10627.php');
660+
}
658661

659662
yield from $this->gatherAssertTypes(__DIR__ . '/data/native-intersection.php');
660663

tests/PHPStan/Analyser/data/bug-10627.php

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Bug10627;
44

5+
use function array_is_list;
56
use function PHPStan\Testing\assertType;
67

78
class HelloWorld
@@ -10,35 +11,40 @@ public function sayHello(): void
1011
{
1112
$list = ['A', 'C', 'B'];
1213
natcasesort($list);
13-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
14+
assertType("array{'A', 'C', 'B'}", $list);
15+
assertType('bool', array_is_list($list));
1416
}
1517

1618
public function sayHello2(): void
1719
{
1820
$list = ['A', 'C', 'B'];
1921
natsort($list);
20-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
22+
assertType("array{'A', 'C', 'B'}", $list);
23+
assertType('bool', array_is_list($list));
2124
}
2225

2326
public function sayHello3(): void
2427
{
2528
$list = ['A', 'C', 'B'];
2629
arsort($list);
27-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
30+
assertType("array{'A', 'C', 'B'}", $list);
31+
assertType('bool', array_is_list($list));
2832
}
2933

3034
public function sayHello4(): void
3135
{
3236
$list = ['A', 'C', 'B'];
3337
asort($list);
34-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
38+
assertType("array{'A', 'C', 'B'}", $list);
39+
assertType('bool', array_is_list($list));
3540
}
3641

3742
public function sayHello5(): void
3843
{
3944
$list = ['A', 'C', 'B'];
4045
ksort($list);
41-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
46+
assertType("array{'A', 'C', 'B'}", $list);
47+
assertType('bool', array_is_list($list));
4248
}
4349

4450
public function sayHello6(): void
@@ -47,7 +53,8 @@ public function sayHello6(): void
4753
uasort($list, function () {
4854

4955
});
50-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
56+
assertType("array{'A', 'C', 'B'}", $list);
57+
assertType('bool', array_is_list($list));
5158
}
5259

5360
public function sayHello7(): void
@@ -56,14 +63,16 @@ public function sayHello7(): void
5663
uksort($list, function () {
5764

5865
});
59-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
66+
assertType("array{'A', 'C', 'B'}", $list);
67+
assertType('bool', array_is_list($list));
6068
}
6169

6270
public function sayHello8(): void
6371
{
6472
$list = ['A', 'C', 'B'];
6573
krsort($list);
66-
assertType("non-empty-array<0|1|2, 'A'|'B'|'C'>", $list);
74+
assertType("array{'A', 'C', 'B'}", $list);
75+
assertType('bool', array_is_list($list));
6776
}
6877

6978
/**
@@ -75,4 +84,12 @@ public function sayHello9(array $list): void
7584
krsort($list);
7685
assertType("array<int<0, max>, string>", $list);
7786
}
87+
88+
public function sayHello10(): void
89+
{
90+
$list = ['a' => 'A', 'c' => 'C', 'b' => 'B'];
91+
krsort($list);
92+
assertType("array{a: 'A', c: 'C', b: 'B'}", $list);
93+
assertType('false', array_is_list($list));
94+
}
7895
}

tests/PHPStan/Analyser/data/param-out.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ function foo15() {
221221
$manifest,
222222
"fooCompare"
223223
);
224-
assertType('non-empty-array<0|1|2, 1|2|3>', $manifest);
224+
assertType('array{1, 2, 3}', $manifest);
225225
}
226226

227227
function fooSpaceship (string $a, string $b): int {
@@ -234,7 +234,7 @@ function foo16() {
234234
$array,
235235
"fooSpaceship"
236236
);
237-
assertType('non-empty-array<0|1, 1|2>', $array);
237+
assertType('array{1, 2}', $array);
238238
}
239239

240240
function fooShuffle() {
@@ -251,6 +251,7 @@ function fooSort() {
251251
$array = ["foo" => 123, "bar" => 456];
252252
sort($array);
253253
assertType('non-empty-list<123|456>', $array);
254+
assertType('true', array_is_list($array));
254255

255256
$emptyArray = [];
256257
sort($emptyArray);

0 commit comments

Comments
 (0)