-
-
Notifications
You must be signed in to change notification settings - Fork 946
Description
Summary of a problem or a feature request
phpstan incorrectly reports that a variable might not be defined. Specifically, the value target of a foreach is reported as might not be defined after the loop, even when there is sufficient information to show that the loop must have iterated at least once for the code to be reached.
Code snippet that reproduces the problem
- https://phpstan.org/r/6762e042fa172646410eca60449b7354
- https://phpstan.org/r/5735aae73a39f48bd76c3a75e5bbf127
- https://phpstan.org/r/3b98070636c0974658810607a3dfec06
- https://phpstan.org/r/d2ccf447a0b83e8280a7a28e81855c4b
Expected output
There should be no error reported. This error is new in phpstan 0.9.2. It did not appear in 0.9.1.
In all four cases, phpstan reports incorrectly that the value variable of a foreach may not be defined after the loop, even though it must be if the code is reached.
In case 1, the value is always defined, because a non-empty array will always result in the foreach value variable being set. In case 2, the array is explicitly checked for non-empty status, but the error is still displayed. (The error is still displayed if the if($arr) test is moved to cover both the foreach and the reference to is variable.)
Cases 3 and 4 are slightly more complicated, because there is a proxy used to determine if the array was empty. In 3, a variable is incremented in each loop iteration, and if non-zero, would indicate the presence of the variable. Case 4 (which most closely resembles my actual code), uses a !== test between two initially null variables, one of which is used as a loop counter, and the other which (in production code) may be changed to obtain the value of the loop counter at some point. In any case, given the initial values of the variables, the test only succeeds if there has been at least one loop iteration, which means the value variable must be present.
I'm uncertain if this is one issue, or multiple issues; if multiple, I can split this issue up as necessary.