Skip to content

Commit 98a7a8e

Browse files
committed
Fix phpstan/phpstan#13629: False report for 2.1.30 release "arrayValues.list" ("Parameter X of array_values is already a list, call has no effect")
1 parent 8b96391 commit 98a7a8e

4 files changed

Lines changed: 51 additions & 6 deletions

File tree

src/Analyser/ExprHandler/AssignHandler.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -991,13 +991,16 @@ private function produceArrayDimFetchAssignValueToWrite(array $dimFetchStack, ar
991991
$offsetType !== null
992992
&& $arrayDimFetch !== null
993993
&& $scope->hasExpressionType($arrayDimFetch)->yes()
994-
&& !$offsetValueType->hasOffsetValueType($offsetType)->no()
995994
) {
996995
$hasOffsetType = null;
997-
if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
998-
$hasOffsetType = new HasOffsetValueType($offsetType, $valueToWrite);
996+
if ($offsetValueType->hasOffsetValueType($offsetType)->no()) {
997+
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite);
998+
} else {
999+
if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
1000+
$hasOffsetType = new HasOffsetValueType($offsetType, $valueToWrite);
1001+
}
1002+
$valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite);
9991003
}
1000-
$valueToWrite = $offsetValueType->setExistingOffsetValueType($offsetType, $valueToWrite);
10011004

10021005
if ($valueToWrite->isArray()->yes()) {
10031006
if ($hasOffsetType !== null) {

src/Type/IntersectionType.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,12 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
981981
}
982982
}
983983

984-
if ($this->isList()->yes() && $this->getIterableValueType()->isArray()->yes()) {
984+
if (
985+
$this->isList()->yes()
986+
&& $valueType->isArray()->yes()
987+
&& $offsetType !== null
988+
&& IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($offsetType)->yes()
989+
) {
985990
$result = TypeCombinator::intersect($result, new AccessoryArrayListType());
986991
}
987992

tests/PHPStan/Analyser/nsrt/bug-10089.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ protected function create_matrix(int $size): array
2222
$matrix[$size - 1][8] = 3;
2323

2424
// non-empty-array<int, non-empty-array<int, 0|3>&hasOffsetValue(8, 3)>
25-
assertType('non-empty-list<non-empty-array<int<0, max>, 0|3>>', $matrix);
25+
assertType('non-empty-array<int, non-empty-array<int<0, max>, 0|3>>', $matrix);
2626

2727
for ($i = 0; $i <= $size; $i++) {
2828
if ($matrix[$i][8] === 0) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13629;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @param array<string, list<array{xmlNamespace: string, namespace: string, name: string}>> $xsdFiles
9+
* @param array<string, list<array{xmlNamespace: string, namespace: string, name: string}>> $groupedByNamespace
10+
* @param array<string, list<string>> $extraNamespaces
11+
*/
12+
function test(array $xsdFiles, array $groupedByNamespace, array $extraNamespaces): void {
13+
foreach ($extraNamespaces as $mergedNamespace) {
14+
if (count($mergedNamespace) < 2) {
15+
continue;
16+
}
17+
18+
$targetNamespace = end($mergedNamespace);
19+
if (!isset($groupedByNamespace[$targetNamespace])) {
20+
continue;
21+
}
22+
$xmlNamespace = $groupedByNamespace[$targetNamespace][0]['xmlNamespace'];
23+
24+
assertType('string', $xmlNamespace);
25+
assertType('non-empty-list<string>&hasOffsetValue(1, string)', $mergedNamespace);
26+
27+
$xsdFiles[$xmlNamespace] = [];
28+
foreach ($mergedNamespace as $namespace) {
29+
foreach ($groupedByNamespace[$namespace] ?? [] as $viewHelper) {
30+
$xsdFiles[$xmlNamespace][$viewHelper['name']] = $viewHelper;
31+
}
32+
}
33+
// After assigning with string keys ($viewHelper['name']), $xsdFiles[$xmlNamespace] should NOT be a list
34+
assertType('array<int<0, max>|string, array{xmlNamespace: string, namespace: string, name: string}>', $xsdFiles[$xmlNamespace]);
35+
$xsdFiles[$xmlNamespace] = array_values($xsdFiles[$xmlNamespace]);
36+
}
37+
}

0 commit comments

Comments
 (0)