Skip to content

Commit 5d64483

Browse files
committed
Fixed assigning nested arrays
1 parent 6b89297 commit 5d64483

File tree

6 files changed

+48
-7
lines changed

6 files changed

+48
-7
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,10 +2298,12 @@ private function processAssignVar(
22982298
$offsetValueTypeStack[] = $offsetValueType;
22992299
}
23002300

2301-
foreach (array_reverse($offsetTypes) as $offsetType) {
2301+
foreach (array_reverse($offsetTypes) as $i => $offsetType) {
23022302
/** @var Type $offsetValueType */
23032303
$offsetValueType = array_pop($offsetValueTypeStack);
2304-
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite);
2304+
2305+
/** @phpstan-ignore-next-line */
2306+
$valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0);
23052307
}
23062308

23072309
if ($var instanceof Variable && is_string($var->name)) {

src/Type/ArrayType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,15 @@ public function getOffsetValueType(Type $offsetType): Type
216216
return $type;
217217
}
218218

219-
public function setOffsetValueType(?Type $offsetType, Type $valueType): Type
219+
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type
220220
{
221221
if ($offsetType === null) {
222222
$offsetType = new IntegerType();
223223
}
224224

225225
return new self(
226226
TypeCombinator::union($this->keyType, self::castToArrayKeyType($offsetType)),
227-
TypeCombinator::union($this->itemType, $valueType)
227+
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType
228228
);
229229
}
230230

src/Type/Constant/ConstantArrayType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ public function getOffsetValueType(Type $offsetType): Type
431431
return new ErrorType(); // undefined offset
432432
}
433433

434-
public function setOffsetValueType(?Type $offsetType, Type $valueType): Type
434+
public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = false): Type
435435
{
436436
$builder = ConstantArrayTypeBuilder::createFromConstantArray($this);
437437
$builder->setOffsetValueType($offsetType, $valueType);

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9889,6 +9889,11 @@ public function dataBug3269(): array
98899889
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3269.php');
98909890
}
98919891

9892+
public function dataAssignNestedArray(): array
9893+
{
9894+
return $this->gatherAssertTypes(__DIR__ . '/data/assign-nested-arrays.php');
9895+
}
9896+
98929897
/**
98939898
* @dataProvider dataBug2574
98949899
* @dataProvider dataBug2577
@@ -9935,6 +9940,7 @@ public function dataBug3269(): array
99359940
* @dataProvider dataInheritPhpDocMerging
99369941
* @dataProvider dataBug3266
99379942
* @dataProvider dataBug3269
9943+
* @dataProvider dataAssignNestedArray
99389944
* @param ConstantStringType $expectedType
99399945
* @param Type $actualType
99409946
*/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace AssignNestedArrays;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function doFoo(int $i)
11+
{
12+
$array = [];
13+
14+
$array[$i]['bar'] = 1;
15+
$array[$i]['baz'] = 2;
16+
17+
assertType('array<int, array(\'bar\' => 1, \'baz\' => 2)>', $array);
18+
}
19+
20+
public function doBar(int $i, int $j)
21+
{
22+
$array = [];
23+
24+
$array[$i][$j]['bar'] = 1;
25+
$array[$i][$j]['baz'] = 2;
26+
27+
echo $array[$i][$j]['bar'];
28+
echo $array[$i][$j]['baz'];
29+
30+
assertType('array<int, array<int, array(\'bar\' => 1, \'baz\' => 2)>>', $array);
31+
}
32+
33+
}

tests/PHPStan/Rules/Arrays/data/nonexistent-offset.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,15 @@ public function arrayWithMultipleKeysAfterForeaches(int $i, int $j)
358358
$array[$i]['baz'] = 2;
359359

360360
echo $array[$i]['bar'];
361-
//echo $array[$i]['baz'];
361+
echo $array[$i]['baz'];
362362

363363
$array = [];
364364

365365
$array[$i][$j]['bar'] = 1;
366366
$array[$i][$j]['baz'] = 2;
367367

368368
echo $array[$i][$j]['bar'];
369-
//echo $array[$i][$j]['baz'];
369+
echo $array[$i][$j]['baz'];
370370
}
371371
}
372372

0 commit comments

Comments
 (0)