Skip to content

Do not report do-while-false pseudo-loops that are interrupted by a break statement#4551

Merged
ondrejmirtes merged 2 commits intophpstan:2.1.xfrom
claudepache:do-break-false
Feb 10, 2026
Merged

Do not report do-while-false pseudo-loops that are interrupted by a break statement#4551
ondrejmirtes merged 2 commits intophpstan:2.1.xfrom
claudepache:do-break-false

Conversation

@claudepache
Copy link
Contributor

This enables support of the do-break-while-false pattern:

do {
    if ($foo) {
        if ($bar) {
            $a = 'baz';
            break;
        }
     }
     $a = foobar($baz);
} while (false); // no doWhile.alwaysFalse error

The error is still reported when the pseudo-loop is not broken with break.

@claudepache
Copy link
Contributor Author

(The second commit did not change semantics, only simplified redundant conditions.)

@ondrejmirtes
Copy link
Member

I rebased the PR. It needs some fixes:


Parse error: tests/PHPStan/Rules/Comparison/data/do-while-loop.php:148
    146| 	}
    147| 
  > 148| 	public function doFoo12(array $a)
    149| 	{
    150| 		do {
Cannot redeclare DoWhileLoopConstantCondition\Foo::doFoo12()

@claudepache
Copy link
Contributor Author

@ondrejmirtes fixed (and I wonder why it didn’t make the test fail, but anyway...)

@ondrejmirtes ondrejmirtes merged commit c7ad25b into phpstan:2.1.x Feb 10, 2026
634 of 639 checks passed
@ondrejmirtes
Copy link
Member

Thank you!

@claudepache claudepache deleted the do-break-false branch February 10, 2026 16:27
@staabm
Copy link
Contributor

staabm commented Feb 10, 2026

@claudepache how did you come up with this construction in PHP?

I am aware of this pattern in languages which have block-scoped variables, but I can't find a use-case in PHP (because variables will be alive even after the block they are assigned/declared in).

no shaming.. I am just curious

@ondrejmirtes
Copy link
Member

@staabm I'd guess it's another way of basically doing goto.

@claudepache
Copy link
Contributor Author

claudepache commented Feb 10, 2026

@staabm Nothing to do with variable scope, only with code flow. Here is an example of use:

// $date_in might be: '2.2025', '02 2025', '02-2025', '2025-02',  '2/2025', '022025', ...
do {
    $date_tmp = explode('.', $date_in);
    if (ctype_digit($date_tmp[1] ?? ''))
        break;
    $date_tmp = explode(' ', $date_in);
    if (ctype_digit($date_tmp[1] ?? ''))
        break;
    $date_tmp = explode('-', $date_in);
    if (ctype_digit($date_tmp[1] ?? ''))
        break;
    $date_tmp = explode('/', $date_in);
    if (ctype_digit($date_tmp[1] ?? ''))
        break;
    if ((strlen($date_in) == 4) || (strlen($date_in) == 6)) {
        $date_tmp[0] = substr($date_in, 0, 2);
        $date_tmp[1] = substr($date_in, 2   );
    }
} while (false);
// $date_tmp is assumed to hold date components ($month and $year in either order)
// continue processing...

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