Skip to content

Commit

Permalink
Support for endless loops
Browse files Browse the repository at this point in the history
  • Loading branch information
herndlm committed Oct 14, 2024
1 parent 6ac62d3 commit 824abe6
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 16 deletions.
13 changes: 9 additions & 4 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1193,10 +1193,8 @@ private function processStmtNode(

if ($alwaysIterates) {
$isAlwaysTerminating = count($finalScopeResult->getExitPointsByType(Break_::class)) === 0;
} elseif ($isIterableAtLeastOnce) {
$isAlwaysTerminating = $finalScopeResult->isAlwaysTerminating();
} else {
$isAlwaysTerminating = false;
$isAlwaysTerminating = $isIterableAtLeastOnce && $finalScopeResult->isAlwaysTerminating();
}
$condScope = $condResult->getFalseyScope();
if (!$isIterableAtLeastOnce) {
Expand Down Expand Up @@ -1313,6 +1311,7 @@ private function processStmtNode(
}

$bodyScope = $initScope;
$alwaysIterates = $stmt->cond === [] && $context->isTopLevel();
$isIterableAtLeastOnce = TrinaryLogic::createYes();
foreach ($stmt->cond as $condExpr) {
$condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, static function (): void {
Expand Down Expand Up @@ -1410,10 +1409,16 @@ private function processStmtNode(
}
}

if ($alwaysIterates) {
$isAlwaysTerminating = count($finalScopeResult->getExitPointsByType(Break_::class)) === 0;
} else {
$isAlwaysTerminating = false; // $finalScopeResult->isAlwaysTerminating() && $isAlwaysIterable
}

return new StatementResult(
$finalScope,
$finalScopeResult->hasYield() || $hasYield,
false/* $finalScopeResult->isAlwaysTerminating() && $isAlwaysIterable*/,
$isAlwaysTerminating,
$finalScopeResult->getExitPointsForOuterLoop(),
array_merge($throwPoints, $finalScopeResult->getThrowPoints()),
array_merge($impurePoints, $finalScopeResult->getImpurePoints()),
Expand Down
12 changes: 12 additions & 0 deletions tests/PHPStan/Analyser/StatementResultTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ public function dataIsAlwaysTerminating(): array
'while (true) { break; }',
false,
],
[
'for (;;) { }',
true,
],
[
'for (;;) { return; }',
true,
],
[
'for (;;) { break; }',
false,
],
[
'do { } while (doFoo());',
false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ public function testStrictComparison(): void
140,
],
[
'Strict comparison using !== between StrictComparison\Foo|null and 1 will always evaluate to true.',
154,
'Strict comparison using === between non-empty-array and null will always evaluate to false.',
150,
],
[
'Strict comparison using === between non-empty-array and null will always evaluate to false.',
164,
'Strict comparison using !== between StrictComparison\Foo|null and 1 will always evaluate to true.',
161,
],
[
'Strict comparison using !== between StrictComparison\Node|null and false will always evaluate to true.',
Expand Down Expand Up @@ -333,7 +333,7 @@ public function testStrictComparisonWithoutAlwaysTrue(): void
],
[
'Strict comparison using === between non-empty-array and null will always evaluate to false.',
164,
150,
],
[
'Strict comparison using === between 1 and 2 will always evaluate to false.',
Expand Down
14 changes: 7 additions & 7 deletions tests/PHPStan/Rules/Comparison/data/strict-comparison.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ public function whileWithTypeChange()

public function forWithTypeChange()
{
for (; $val = $this->returnArray();) {
if ($val === null) {

}
$val = null;
}

$foo = null;
for (;;) {
if ($foo !== null) {
Expand All @@ -159,13 +166,6 @@ public function forWithTypeChange()
$foo = new self();
}
}

for (; $val = $this->returnArray();) {
if ($val === null) {

}
$val = null;
}
}

private function returnArray(): array
Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Rules/Missing/MissingReturnRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,4 +325,10 @@ public function testBug9309(): void
$this->analyse([__DIR__ . '/data/bug-9309.php'], []);
}

public function testBug8463(): void
{
$this->checkExplicitMixedMissingReturn = true;
$this->analyse([__DIR__ . '/data/bug-8463.php'], []);
}

}
26 changes: 26 additions & 0 deletions tests/PHPStan/Rules/Missing/data/bug-8463.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Bug8463;

function f1() : int
{
while(true)
{
if(rand() === rand())
{
return 1;
}
}
}


function f2() : int
{
for(;;)
{
if(rand() === rand())
{
return 1;
}
}
}

0 comments on commit 824abe6

Please sign in to comment.