Skip to content

Commit 5473b67

Browse files
committed
array_push preserves list
1 parent 927d71f commit 5473b67

File tree

6 files changed

+95
-3
lines changed

6 files changed

+95
-3
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3145,9 +3145,13 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
31453145

31463146
if ($constantArray->isConstantArray()->yes() && $nonConstantArrayWasUnpacked) {
31473147
$array = new ArrayType($constantArray->generalize(GeneralizePrecision::lessSpecific())->getIterableKeyType(), $constantArray->getIterableValueType());
3148+
$isList = $constantArray->isList()->yes();
31483149
$constantArray = $constantArray->isIterableAtLeastOnce()->yes()
31493150
? TypeCombinator::intersect($array, new NonEmptyArrayType())
31503151
: $array;
3152+
$constantArray = $isList
3153+
? AccessoryArrayListType::intersectWith($constantArray)
3154+
: $constantArray;
31513155
}
31523156

31533157
$newArrayTypes[] = $constantArray;

tests/PHPStan/Analyser/data/array-push.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function arrayPushConstantArray(): void
6666
/** @var array<bool|null> $f1 */
6767
$f1 = [];
6868
array_push($f, ...$f1);
69-
assertType('non-empty-array<int<0, max>, 17|bool|null>', $f);
69+
assertType('non-empty-list<17|bool|null>', $f);
7070

7171
$g = [new stdClass()];
7272
array_push($g, ...[new stdClass(), new stdClass()]);

tests/PHPStan/Analyser/data/array-unshift.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function arrayUnshiftConstantArray(): void
6666
/** @var array<bool|null> $f1 */
6767
$f1 = [];
6868
array_unshift($f, ...$f1);
69-
assertType('non-empty-array<int<0, max>, 17|bool|null>', $f);
69+
assertType('non-empty-list<17|bool|null>', $f);
7070

7171
$g = [new stdClass()];
7272
array_unshift($g, ...[new stdClass(), new stdClass()]);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function doFoo(): void
2727
array_push($d, $thing);
2828
}
2929

30-
assertType('array<int<0, max>, array{a: int, b: string}>', $b);
30+
assertType('list<array{a: int, b: string}>', $b);
3131
assertType('list<array{a: int, b: string}>', $c);
3232
assertType('list<array{a: int, b: string}>', $d);
3333
}

tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,4 +998,9 @@ public function testBug5008(): void
998998
$this->analyse([__DIR__ . '/data/bug-5008.php'], []);
999999
}
10001000

1001+
public function testArrayPushPreservesList(): void
1002+
{
1003+
$this->analyse([__DIR__ . '/data/array-push-preserves-list.php'], []);
1004+
}
1005+
10011006
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
namespace ArrayPushPreservesList;
4+
5+
use function array_unshift;
6+
7+
class Foo
8+
{
9+
10+
/**
11+
* @param list<int> $a
12+
* @return list<int>
13+
*/
14+
public function doFoo(array $a): array
15+
{
16+
array_push($a, ...$a);
17+
18+
return $a;
19+
}
20+
21+
/**
22+
* @param list<int> $a
23+
* @return list<int>
24+
*/
25+
public function doFoo2(array $a): array
26+
{
27+
array_push($a, ...[1, 2, 3]);
28+
29+
return $a;
30+
}
31+
32+
/**
33+
* @param list<int> $a
34+
* @return list<int>
35+
*/
36+
public function doFoo3(array $a): array
37+
{
38+
$b = [1, 2, 3];
39+
array_push($b, ...$a);
40+
41+
return $b;
42+
}
43+
44+
}
45+
46+
class Bar
47+
{
48+
49+
/**
50+
* @param list<int> $a
51+
* @return list<int>
52+
*/
53+
public function doFoo(array $a): array
54+
{
55+
array_unshift($a, ...$a);
56+
57+
return $a;
58+
}
59+
60+
/**
61+
* @param list<int> $a
62+
* @return list<int>
63+
*/
64+
public function doFoo2(array $a): array
65+
{
66+
array_unshift($a, ...[1, 2, 3]);
67+
68+
return $a;
69+
}
70+
71+
/**
72+
* @param list<int> $a
73+
* @return list<int>
74+
*/
75+
public function doFoo3(array $a): array
76+
{
77+
$b = [1, 2, 3];
78+
array_unshift($b, ...$a);
79+
80+
return $b;
81+
}
82+
83+
}

0 commit comments

Comments
 (0)