Skip to content

Commit

Permalink
Array after array_push / array_unshift call can still be empty
Browse files Browse the repository at this point in the history
  • Loading branch information
herndlm committed Jun 17, 2022
1 parent d60c7dc commit 82dfce1
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 10 deletions.
14 changes: 10 additions & 4 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -1825,7 +1825,7 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression

/**
* @param Arg[] $callArgs
* @param callable(?Type, Type, bool=): void $setOffsetValueType
* @param callable(?Type, Type, bool): void $setOffsetValueType
*/
$setOffsetValueTypes = static function (Scope $scope, array $callArgs, callable $setOffsetValueType, ?bool &$nonConstantArrayWasUnpacked = null): void {
foreach ($callArgs as $callArg) {
Expand All @@ -1850,7 +1850,7 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
}
continue;
}
$setOffsetValueType(null, $callArgType);
$setOffsetValueType(null, $callArgType, false);
}
};

Expand All @@ -1861,7 +1861,7 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
$setOffsetValueTypes(
$scope,
$callArgs,
static function (?Type $offsetType, Type $valueType, bool $optional = false) use (&$arrayTypeBuilder): void {
static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arrayTypeBuilder): void {
$arrayTypeBuilder->setOffsetValueType($offsetType, $valueType, $optional);
},
$nonConstantArrayWasUnpacked,
Expand Down Expand Up @@ -1890,8 +1890,14 @@ static function (?Type $offsetType, Type $valueType, bool $optional = false) use
$setOffsetValueTypes(
$scope,
$callArgs,
static function (?Type $offsetType, Type $valueType) use (&$arrayType): void {
static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arrayType): void {
$isIterableAtLeastOnce = $arrayType->isIterableAtLeastOnce()->yes() || !$optional;
$arrayType = $arrayType->setOffsetValueType($offsetType, $valueType);
if ($isIterableAtLeastOnce) {
return;
}

$arrayType = TypeCombinator::union(...TypeUtils::getArrays($arrayType));
},
);
}
Expand Down
10 changes: 7 additions & 3 deletions tests/PHPStan/Analyser/data/array-push.php
Expand Up @@ -13,10 +13,14 @@
* @param non-empty-array<int> $c
* @param array<int|string> $d
*/
function arrayPush(array $a, array $b, array $c, array $d): void
function arrayPush(array $a, array $b, array $c, array $d, array $arr): void
{
array_push($a, ...$b);
assertType('non-empty-array<int|string>', $a);
assertType('array<int|string>', $a);

/** @var non-empty-array<string> $arr */
array_push($arr, ...$b);
assertType('non-empty-array<int|string>', $arr);

array_push($b, ...[]);
assertType('array<int>', $b);
Expand All @@ -27,7 +31,7 @@ function arrayPush(array $a, array $b, array $c, array $d): void
/** @var array<bool|null> $d1 */
$d1 = [];
array_push($d, ...$d1);
assertType('non-empty-array<bool|int|string|null>', $d);
assertType('array<bool|int|string|null>', $d);
}

function arrayPushConstantArray(): void
Expand Down
10 changes: 7 additions & 3 deletions tests/PHPStan/Analyser/data/array-unshift.php
Expand Up @@ -13,10 +13,14 @@
* @param non-empty-array<int> $c
* @param array<int|string> $d
*/
function arrayUnshift(array $a, array $b, array $c, array $d): void
function arrayUnshift(array $a, array $b, array $c, array $d, array $arr): void
{
array_unshift($a, ...$b);
assertType('non-empty-array<int|string>', $a);
assertType('array<int|string>', $a);

/** @var non-empty-array<string> $arr */
array_unshift($arr, ...$b);
assertType('non-empty-array<int|string>', $arr);

array_unshift($b, ...[]);
assertType('array<int>', $b);
Expand All @@ -27,7 +31,7 @@ function arrayUnshift(array $a, array $b, array $c, array $d): void
/** @var array<bool|null> $d1 */
$d1 = [];
array_unshift($d, ...$d1);
assertType('non-empty-array<bool|int|string|null>', $d);
assertType('array<bool|int|string|null>', $d);
}

function arrayUnshiftConstantArray(): void
Expand Down
8 changes: 8 additions & 0 deletions tests/PHPStan/Rules/Variables/EmptyRuleTest.php
Expand Up @@ -169,4 +169,12 @@ public function testBug7318(): void
$this->analyse([__DIR__ . '/../Properties/data/bug-7318.php'], []);
}

public function testBug7424(): void
{
$this->treatPhpDocTypesAsCertain = true;
$this->strictUnnecessaryNullsafePropertyFetch = false;

$this->analyse([__DIR__ . '/data/bug-7424.php'], []);
}

}
35 changes: 35 additions & 0 deletions tests/PHPStan/Rules/Variables/data/bug-7424.php
@@ -0,0 +1,35 @@
<?php

namespace Bug7424;

class Test
{
public function run(): void
{
$data = $this->getInitData();

array_push($data, ...$this->getExtra());

if (empty($data)) {
return;
}

echo 'Proceeding to process data';
}

/**
* @return string[]
*/
protected function getInitData(): array
{
return [];
}

/**
* @return string[]
*/
protected function getExtra(): array
{
return [];
}
}

0 comments on commit 82dfce1

Please sign in to comment.