Skip to content

Commit 39e8286

Browse files
herndlmondrejmirtes
authored andcommitted
Fix array_push / array_unshift with ConstantArrayType arguments
1 parent 9bb13b0 commit 39e8286

File tree

5 files changed

+44
-7
lines changed

5 files changed

+44
-7
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,17 +1858,23 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
18581858
if ($callArgType->isIterableAtLeastOnce()->no()) {
18591859
continue;
18601860
}
1861-
if (!$callArgType instanceof ConstantArrayType) {
1861+
1862+
if ($callArgType instanceof ConstantArrayType) {
1863+
$iterableValueTypes = $callArgType->getValueTypes();
1864+
} else {
1865+
$iterableValueTypes = [$callArgType->getIterableValueType()];
18621866
$nonConstantArrayWasUnpacked = true;
18631867
}
1864-
$iterableValueType = $callArgType->getIterableValueType();
1868+
18651869
$isOptional = !$callArgType->isIterableAtLeastOnce()->yes();
1866-
if ($iterableValueType instanceof UnionType) {
1867-
foreach ($iterableValueType->getTypes() as $innerType) {
1868-
$setOffsetValueType(null, $innerType, $isOptional);
1870+
foreach ($iterableValueTypes as $iterableValueType) {
1871+
if ($iterableValueType instanceof UnionType) {
1872+
foreach ($iterableValueType->getTypes() as $innerType) {
1873+
$setOffsetValueType(null, $innerType, $isOptional);
1874+
}
1875+
} else {
1876+
$setOffsetValueType(null, $iterableValueType, $isOptional);
18691877
}
1870-
} else {
1871-
$setOffsetValueType(null, $iterableValueType, $isOptional);
18721878
}
18731879
continue;
18741880
}

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ public function dataFileAsserts(): iterable
794794

795795
yield from $this->gatherAssertTypes(__DIR__ . '/data/preg_filter.php');
796796
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5759.php');
797+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5783.php');
797798
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5668.php');
798799
yield from $this->gatherAssertTypes(__DIR__ . '/data/generics-empty-array.php');
799800
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-5757.php');

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

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

33
namespace ArrayPush;
44

5+
use stdClass;
6+
57
use function array_push;
68
use function PHPStan\Testing\assertType;
79

@@ -55,4 +57,8 @@ function arrayPushConstantArray(): void
5557
$f1 = [];
5658
array_push($f, ...$f1);
5759
assertType('non-empty-array<int, bool|int|null>', $f);
60+
61+
$g = [new stdClass()];
62+
array_push($g, ...[new stdClass(), new stdClass()]);
63+
assertType('array{stdClass, stdClass, stdClass}', $g);
5864
}

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

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

33
namespace ArrayUnshift;
44

5+
use stdClass;
6+
57
use function array_unshift;
68
use function PHPStan\Testing\assertType;
79

@@ -55,4 +57,8 @@ function arrayUnshiftConstantArray(): void
5557
$f1 = [];
5658
array_unshift($f, ...$f1);
5759
assertType('non-empty-array<int, bool|int|null>', $f);
60+
61+
$g = [new stdClass()];
62+
array_unshift($g, ...[new stdClass(), new stdClass()]);
63+
assertType('array{stdClass, stdClass, stdClass}', $g);
5864
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug5783;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld {}
8+
9+
function foo(): void
10+
{
11+
$a = [new HelloWorld()];
12+
assertType('array{Bug5783\HelloWorld}', $a);
13+
$b = [new HelloWorld(), new HelloWorld(), new HelloWorld()];
14+
assertType('array{Bug5783\HelloWorld, Bug5783\HelloWorld, Bug5783\HelloWorld}', $b);
15+
16+
array_push($a, ...$b);
17+
assertType('array{Bug5783\HelloWorld, Bug5783\HelloWorld, Bug5783\HelloWorld, Bug5783\HelloWorld}', $a);
18+
}

0 commit comments

Comments
 (0)