Skip to content

Fix #5865: Do-while loop broken by exception not supported (reported as always-true)#5078

Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-hhethxe
Closed

Fix #5865: Do-while loop broken by exception not supported (reported as always-true)#5078
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-hhethxe

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

A do { ... } while (true); loop whose body contains a function call with an explicit @throws annotation was incorrectly reported as "Do-while loop condition is always true." The loop is intentionally infinite and exits only via an exception, which is a valid pattern.

Changes

  • src/Node/DoWhileLoopConditionNode.php — Added $throwPoints parameter and getThrowPoints() method so the rule can inspect throw points from the loop body
  • src/Analyser/NodeScopeResolver.php — Pass throw points alongside exit points when constructing DoWhileLoopConditionNode
  • src/Rules/Comparison/DoWhileLoopConstantConditionRule.php — When the condition is always true, also check for explicit throw points; if any exist, the loop can exit via exception and the warning is suppressed
  • tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php — Added testBug5865
  • tests/PHPStan/Rules/Comparison/data/bug-5865.php — Regression test data

Root cause

The rule already recognized direct throw statements and break/return as valid exit mechanisms for do-while(true) loops (via exit points). However, function calls annotated with @throws generate "throw points" rather than "exit points." The rule did not check throw points, so it could not see that the loop body had an explicit way to exit via exception. The fix adds explicit throw point checking to the rule.

Test

The regression test reproduces the exact scenario from the issue: a do-while(true) loop inside a try-catch where the loop body calls a method annotated with @throws RuntimeException. The test expects no errors.

Fixes phpstan/phpstan#5865

…oints

- DoWhileLoopConstantConditionRule now considers explicit throw points as
  valid loop exit mechanisms, suppressing the "always true" warning
- Added throw points to DoWhileLoopConditionNode alongside exit points
- Updated NodeScopeResolver to pass throw points when creating the node
- New regression test in tests/PHPStan/Rules/Comparison/data/bug-5865.php

Closes phpstan/phpstan#5865
Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno what you think about this fix @staabm

To me, since lot of method has throws phpdoc, I feel like it will not report always true while loop anymore.

public function sayHello(): void
	{
			do {
				$this->foo();
			} while (true);
	}

should be still reported for instance.

@staabm
Copy link
Contributor

staabm commented Feb 27, 2026

@VincentLanglet you could add test coverage for your mentioned example, close this PR and let the bot try a 2nd time after your case is covered in tests

@VincentLanglet
Copy link
Contributor

Closing for now because of phpstan/phpstan#5865 (comment)

@staabm staabm deleted the create-pull-request/patch-hhethxe branch February 28, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants