Skip to content

Commit

Permalink
array_push preserves list
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 28, 2024
1 parent 927d71f commit 5473b67
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3145,9 +3145,13 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra

if ($constantArray->isConstantArray()->yes() && $nonConstantArrayWasUnpacked) {
$array = new ArrayType($constantArray->generalize(GeneralizePrecision::lessSpecific())->getIterableKeyType(), $constantArray->getIterableValueType());
$isList = $constantArray->isList()->yes();
$constantArray = $constantArray->isIterableAtLeastOnce()->yes()
? TypeCombinator::intersect($array, new NonEmptyArrayType())
: $array;
$constantArray = $isList
? AccessoryArrayListType::intersectWith($constantArray)
: $constantArray;
}

$newArrayTypes[] = $constantArray;
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/array-push.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function arrayPushConstantArray(): void
/** @var array<bool|null> $f1 */
$f1 = [];
array_push($f, ...$f1);
assertType('non-empty-array<int<0, max>, 17|bool|null>', $f);
assertType('non-empty-list<17|bool|null>', $f);

$g = [new stdClass()];
array_push($g, ...[new stdClass(), new stdClass()]);
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/array-unshift.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function arrayUnshiftConstantArray(): void
/** @var array<bool|null> $f1 */
$f1 = [];
array_unshift($f, ...$f1);
assertType('non-empty-array<int<0, max>, 17|bool|null>', $f);
assertType('non-empty-list<17|bool|null>', $f);

$g = [new stdClass()];
array_unshift($g, ...[new stdClass(), new stdClass()]);
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/bug-7115.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function doFoo(): void
array_push($d, $thing);
}

assertType('array<int<0, max>, array{a: int, b: string}>', $b);
assertType('list<array{a: int, b: string}>', $b);
assertType('list<array{a: int, b: string}>', $c);
assertType('list<array{a: int, b: string}>', $d);
}
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -998,4 +998,9 @@ public function testBug5008(): void
$this->analyse([__DIR__ . '/data/bug-5008.php'], []);
}

public function testArrayPushPreservesList(): void
{
$this->analyse([__DIR__ . '/data/array-push-preserves-list.php'], []);
}

}
83 changes: 83 additions & 0 deletions tests/PHPStan/Rules/Methods/data/array-push-preserves-list.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace ArrayPushPreservesList;

use function array_unshift;

class Foo
{

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo(array $a): array
{
array_push($a, ...$a);

return $a;
}

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo2(array $a): array
{
array_push($a, ...[1, 2, 3]);

return $a;
}

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo3(array $a): array
{
$b = [1, 2, 3];
array_push($b, ...$a);

return $b;
}

}

class Bar
{

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo(array $a): array
{
array_unshift($a, ...$a);

return $a;
}

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo2(array $a): array
{
array_unshift($a, ...[1, 2, 3]);

return $a;
}

/**
* @param list<int> $a
* @return list<int>
*/
public function doFoo3(array $a): array
{
$b = [1, 2, 3];
array_unshift($b, ...$a);

return $b;
}

}

0 comments on commit 5473b67

Please sign in to comment.