Skip to content

Commit b1d90c1

Browse files
authored
Merge branch refs/heads/2.1.x into 2.2.x
2 parents 65b7945 + 4919ff4 commit b1d90c1

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,11 +4536,14 @@ private function inferForLoopExpressions(For_ $stmt, Expr $lastCondExpr, Mutatin
45364536
&& $stmt->init[0]->var->name === $lastCondExpr->left->name
45374537
) {
45384538
$arrayArg = $lastCondExpr->right->getArgs()[0]->value;
4539-
$bodyScope = $bodyScope->assignExpression(
4540-
new ArrayDimFetch($lastCondExpr->right->getArgs()[0]->value, $lastCondExpr->left),
4541-
$bodyScope->getType($arrayArg)->getIterableValueType(),
4542-
$bodyScope->getNativeType($arrayArg)->getIterableValueType(),
4543-
);
4539+
$arrayType = $bodyScope->getType($arrayArg);
4540+
if ($arrayType->isList()->yes()) {
4541+
$bodyScope = $bodyScope->assignExpression(
4542+
new ArrayDimFetch($lastCondExpr->right->getArgs()[0]->value, $lastCondExpr->left),
4543+
$arrayType->getIterableValueType(),
4544+
$bodyScope->getNativeType($arrayArg)->getIterableValueType(),
4545+
);
4546+
}
45444547
}
45454548

45464549
// count($items) > $i
@@ -4557,11 +4560,14 @@ private function inferForLoopExpressions(For_ $stmt, Expr $lastCondExpr, Mutatin
45574560
&& $stmt->init[0]->var->name === $lastCondExpr->right->name
45584561
) {
45594562
$arrayArg = $lastCondExpr->left->getArgs()[0]->value;
4560-
$bodyScope = $bodyScope->assignExpression(
4561-
new ArrayDimFetch($lastCondExpr->left->getArgs()[0]->value, $lastCondExpr->right),
4562-
$bodyScope->getType($arrayArg)->getIterableValueType(),
4563-
$bodyScope->getNativeType($arrayArg)->getIterableValueType(),
4564-
);
4563+
$arrayType = $bodyScope->getType($arrayArg);
4564+
if ($arrayType->isList()->yes()) {
4565+
$bodyScope = $bodyScope->assignExpression(
4566+
new ArrayDimFetch($lastCondExpr->left->getArgs()[0]->value, $lastCondExpr->right),
4567+
$arrayType->getIterableValueType(),
4568+
$bodyScope->getNativeType($arrayArg)->getIterableValueType(),
4569+
);
4570+
}
45654571
}
45664572
}
45674573

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,4 +1240,20 @@ public function testBug14234(): void
12401240
]);
12411241
}
12421242

1243+
public function testBug13773(): void
1244+
{
1245+
$this->reportPossiblyNonexistentGeneralArrayOffset = true;
1246+
1247+
$this->analyse([__DIR__ . '/data/bug-13773.php'], [
1248+
[
1249+
'Offset int<0, max> might not exist on non-empty-array<int, string>.',
1250+
14,
1251+
],
1252+
[
1253+
'Offset int<0, max> might not exist on non-empty-array<int, string>.',
1254+
38,
1255+
],
1256+
]);
1257+
}
1258+
12431259
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13773;
4+
5+
/** @return array<int, string> */
6+
function getArray(): array {
7+
return [100 => "hey"];
8+
}
9+
10+
function testNonListArray(): void
11+
{
12+
$array = getArray();
13+
for ($i = 0; $i < count($array); $i++) {
14+
$a = $array[$i];
15+
}
16+
}
17+
18+
/** @param list<string> $list */
19+
function testList(array $list): void
20+
{
21+
for ($i = 0; $i < count($list); $i++) {
22+
$a = $list[$i];
23+
}
24+
}
25+
26+
/** @param list<string> $list */
27+
function testListReversed(array $list): void
28+
{
29+
for ($i = 0; count($list) > $i; ++$i) {
30+
$a = $list[$i];
31+
}
32+
}
33+
34+
/** @param array<int, string> $array */
35+
function testNonListReversed(array $array): void
36+
{
37+
for ($i = 0; count($array) > $i; ++$i) {
38+
$a = $array[$i];
39+
}
40+
}

0 commit comments

Comments
 (0)