Skip to content

Commit 5f2620c

Browse files
committed
Fix lost list-type if substituted a element via loop
1 parent 17beb01 commit 5f2620c

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

Diff for: src/Analyser/NodeScopeResolver.php

+4
Original file line numberDiff line numberDiff line change
@@ -5482,6 +5482,10 @@ private function processAssignVar(
54825482
}
54835483

54845484
if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) {
5485+
if ($varType->isList()->yes() && $scope->hasExpressionType($originalVar)->yes()) {
5486+
$valueToWrite = TypeCombinator::intersect($valueToWrite, new AccessoryArrayListType());
5487+
}
5488+
54855489
if ($var instanceof Variable && is_string($var->name)) {
54865490
$nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope);
54875491
$scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes());

Diff for: tests/PHPStan/Analyser/nsrt/bug-12274.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug12274;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @param non-empty-list<int> $items
9+
*
10+
* @return non-empty-list<int>
11+
*/
12+
function getItems(array $items): array
13+
{
14+
foreach ($items as $index => $item) {
15+
$items[$index] = 1;
16+
}
17+
18+
assertType('non-empty-list<int>', $items);
19+
return $items;
20+
}
21+
22+
/**
23+
* @param non-empty-list<int> $items
24+
*
25+
* @return non-empty-list<int>
26+
*/
27+
function getItemsByModifiedIndex(array $items): array
28+
{
29+
foreach ($items as $index => $item) {
30+
$index++;
31+
32+
$items[$index] = 1;
33+
}
34+
35+
assertType('non-empty-array<int<0, max>, int>', $items);
36+
return $items;
37+
}

Diff for: tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php

+14
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,18 @@ public function testBug11301(): void
345345
]);
346346
}
347347

348+
public function testBug12274(): void
349+
{
350+
$this->checkExplicitMixed = true;
351+
$this->checkNullables = true;
352+
353+
$this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-12274.php'], [
354+
[
355+
'Function Bug12274\getItemsByModifiedIndex() should return non-empty-list<int> but returns non-empty-array<int<0, max>, int>.',
356+
36,
357+
'non-empty-array<int<0, max>, int> might not be a list.',
358+
],
359+
]);
360+
}
361+
348362
}

0 commit comments

Comments
 (0)