Skip to content

Commit a0c0660

Browse files
github-actions[bot]phpstan-bot
authored andcommitted
Fix wrongly reported empty array when using byRef in array items
- Widen variable type to mixed when passed by reference inside an array literal ([&$var, ...]) - This fixes false positives like "Comparison operation > between 0 and 0 is always false" when variables are passed by reference through call_user_func_array - Added regression test in tests/PHPStan/Analyser/nsrt/bug-6799.php - The root cause was that ArrayHandler did not account for byRef array items, so PHPStan retained the initial precise type (e.g. array{}) even after a reference was created Closes phpstan/phpstan#6799
1 parent 9bbd518 commit a0c0660

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/Analyser/ExprHandler/ArrayHandler.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PHPStan\Node\LiteralArrayItem;
1616
use PHPStan\Node\LiteralArrayNode;
1717
use PHPStan\Reflection\InitializerExprTypeResolver;
18+
use PHPStan\Type\MixedType;
1819
use PHPStan\Type\Type;
1920
use function array_merge;
2021

@@ -66,6 +67,11 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
6667
$impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints());
6768
$isAlwaysTerminating = $isAlwaysTerminating || $valueResult->isAlwaysTerminating();
6869
$scope = $valueResult->getScope();
70+
if (!$arrayItem->byRef) {
71+
continue;
72+
}
73+
74+
$scope = $scope->assignExpression($arrayItem->value, new MixedType(), new MixedType());
6975
}
7076
$nodeScopeResolver->callNodeCallback($nodeCallback, new LiteralArrayNode($expr, $itemNodes), $scope, $storage);
7177

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug6799;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
/**
10+
* @param string[] $where
11+
* @param string $sqlTableName
12+
* @param mixed[] $filter
13+
* @param string $value
14+
*/
15+
protected function listingAddWhereFilterAtableDefault(array &$where, string $sqlTableName, array $filter, string $value): void
16+
{
17+
if ($value != "" && !empty($filter) && !empty($filter['sql']) && is_string($filter['sql'])) {
18+
$where[] = "`" . $sqlTableName . "`.`" . (string)$filter['sql'] . "` = '" . $value . "'";
19+
}
20+
}
21+
22+
/**
23+
* @param string[] $filterValues
24+
* @param string[] $where
25+
* @param string[] $tables
26+
* @param mixed[] $filters
27+
*/
28+
protected function listingAddWhereFilterAtable(array $filterValues, array &$where, array &$tables, array $filters): void
29+
{
30+
if (!empty($filterValues) && !empty($filters)) {
31+
$whereFilter = array();
32+
foreach ($filterValues as $type => $value) {
33+
call_user_func_array(array($this, 'listingAddWhereFilterAtableDefault'), array(&$whereFilter, 'xxxx', $filters[$type], $value));
34+
}
35+
assertType('mixed', $whereFilter);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)