Skip to content

Commit 7cca523

Browse files
VincentLangletphpstan-bot
authored andcommitted
Fix incorrect type-narrowing with polluteScopeWithAlwaysIterableForeach
- Fixed processAlwaysIterableForeachScopeWithoutPollute using stale conditional expressions from before the foreach body, which caused variable aliases (e.g. $current = $initial) to persist even after reassignment inside the foreach - Changed to use $finalScope->conditionalExpressions which properly reflects invalidated aliases from foreach body assignments - New regression test in tests/PHPStan/Analyser/data/bug-14446.php Closes phpstan/phpstan#14446
1 parent da259bd commit 7cca523

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3877,7 +3877,7 @@ public function processAlwaysIterableForeachScopeWithoutPollute(self $finalScope
38773877
$this->getNamespace(),
38783878
$expressionTypes,
38793879
$nativeTypes,
3880-
$this->conditionalExpressions,
3880+
$finalScope->conditionalExpressions,
38813881
$this->inClosureBindScopeClasses,
38823882
$this->anonymousFunctionReflection,
38833883
$this->inFirstLevelStatement,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PHPStan\Testing\TypeInferenceTestCase;
6+
use PHPUnit\Framework\Attributes\DataProvider;
7+
8+
class Bug14446Test extends TypeInferenceTestCase
9+
{
10+
11+
public static function dataFileAsserts(): iterable
12+
{
13+
yield from self::gatherAssertTypes(__DIR__ . '/data/bug-14446.php');
14+
}
15+
16+
/**
17+
* @param mixed ...$args
18+
*/
19+
#[DataProvider('dataFileAsserts')]
20+
public function testFileAsserts(
21+
string $assertType,
22+
string $file,
23+
...$args,
24+
): void
25+
{
26+
$this->assertFileAsserts($assertType, $file, ...$args);
27+
}
28+
29+
public static function getAdditionalConfigFiles(): array
30+
{
31+
return [
32+
__DIR__ . '/bug-14446.neon',
33+
];
34+
}
35+
36+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
polluteScopeWithAlwaysIterableForeach: false
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14446;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function test(bool $initial): void {
8+
$current = $initial;
9+
10+
while (true) {
11+
assertType('bool', $initial);
12+
if (!$current) {
13+
assertType('bool', $initial);
14+
break;
15+
}
16+
17+
$items = [1];
18+
foreach ($items as $item) {
19+
$current = false;
20+
}
21+
}
22+
23+
assertType('bool', $initial);
24+
}

0 commit comments

Comments
 (0)