Skip to content

Commit 14592dd

Browse files
committed
Specify existent offset with key variable when entering foreach
1 parent 62ac4d9 commit 14592dd

4 files changed

Lines changed: 42 additions & 7 deletions

File tree

src/Analyser/MutatingScope.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3143,6 +3143,13 @@ public function enterForeachKey(Expr $iteratee, string $keyName): self
31433143
$scope = $this->assignVariable($keyName, $iterateeType->getIterableKeyType());
31443144
$scope->nativeExpressionTypes[sprintf('$%s', $keyName)] = $nativeIterateeType->getIterableKeyType();
31453145

3146+
if ($iterateeType->isArray()->yes()) {
3147+
$scope = $scope->specifyExpressionType(
3148+
new Expr\ArrayDimFetch($iteratee, new Variable($keyName)),
3149+
$iterateeType->getIterableValueType(),
3150+
);
3151+
}
3152+
31463153
return $scope;
31473154
}
31483155

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,12 +429,7 @@ public function testBug7142(): void
429429
public function testBug6000(): void
430430
{
431431
$this->checkExplicitMixed = true;
432-
$this->analyse([__DIR__ . '/data/bug-6000.php'], [
433-
[
434-
'Offset \'classmap\' does not exist on array{psr-4?: array<string, array<string>|string>, classmap?: array<int, string>}.',
435-
12,
436-
],
437-
]);
432+
$this->analyse([__DIR__ . '/data/bug-6000.php'], []);
438433
}
439434

440435
public function testBug5743(): void
@@ -508,4 +503,9 @@ public function testBug7763(): void
508503
$this->analyse([__DIR__ . '/data/bug-7763.php'], []);
509504
}
510505

506+
public function testSpecifyExistentOffsetWhenEnteringForeach(): void
507+
{
508+
$this->analyse([__DIR__ . '/data/specify-existent-offset-when-entering-foreach.php'], []);
509+
}
510+
511511
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace SpecifyExistentOffsetWhenEnteringForeach;
4+
5+
class Foo
6+
{
7+
8+
public function doFoo(string $s): void
9+
{
10+
$hintsToFind = ['ext-' => 0, 'lib-' => 0, 'php' => 99, 'composer' => 99];
11+
foreach ($hintsToFind as $hintPrefix => $hintCount) {
12+
if (str_starts_with($s, $hintPrefix)) {
13+
if ($hintCount === 0 || $hintCount >= 99) {
14+
$hintsToFind[$hintPrefix]++;
15+
} elseif ($hintCount === 1) {
16+
unset($hintsToFind[$hintPrefix]);
17+
}
18+
}
19+
}
20+
}
21+
22+
}

tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ public function testFile(): void
5050

5151
public function testBug6000(): void
5252
{
53-
$this->analyse([__DIR__ . '/../Arrays/data/bug-6000.php'], []);
53+
$this->analyse([__DIR__ . '/../Arrays/data/bug-6000.php'], [
54+
[
55+
// shouldn't be happening...
56+
'Parameter #2 $array of function implode expects array<string>, array<int|string, array<string>|string> given.',
57+
12,
58+
],
59+
]);
5460
}
5561

5662
}

0 commit comments

Comments
 (0)