-
Notifications
You must be signed in to change notification settings - Fork 542
Improve for
loop initial statement scope pollution
#3617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve for
loop initial statement scope pollution
#3617
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I'd say this is a new feature so one rule regression test isn't enough. We should have a new NodeScopeResolverTest file that covers all the branches with assertType, assertNativeType and assertVariableCertainty calls.
Added more tests that should cover all the new code and also duplicated them to see how it behaves with the default when With my change reverted, tests fail like this
|
Thank you! |
ah I just noticed a new line too much after the namespace of the test files :P also wanted to add the diff between scope pollution on and off: --- tests/PHPStan/Analyser/nsrt/for-loop.php 2024-11-10 13:55:39.808980414 +0100
+++ tests/PHPStan/Analyser/data/for-loop-no-scope-pollution.php 2024-11-10 13:55:39.685646935 +0100
@@ -1,6 +1,6 @@
<?php declare(strict_types=1);
-namespace ForLoop;
+namespace ForLoopNoScopePollution;
use PHPStan\TrinaryLogic;
use function PHPStan\Testing\assertNativeType;
@@ -22,7 +22,7 @@
assertType('int<10, max>', $i);
assertNativeType('int<10, max>', $i);
- assertVariableCertainty(TrinaryLogic::createYes(), $i);
+ assertVariableCertainty(TrinaryLogic::createMaybe(), $i);
assertType('int<min, 10>', $j);
assertNativeType('int<min, 10>', $j);
@@ -53,7 +53,7 @@
assertType('int<0, max>', $i);
assertNativeType('int<0, max>', $i);
- assertVariableCertainty(TrinaryLogic::createYes(), $i);
+ assertVariableCertainty(TrinaryLogic::createMaybe(), $i);
assertType('int<min, 10>', $j);
assertNativeType('int<min, 10>', $j);
@@ -82,12 +82,12 @@
$c = rand(0, 1);
}
- assertType('0', $i);
- assertNativeType('0', $i);
- assertVariableCertainty(TrinaryLogic::createYes(), $i);
+ assertType('*ERROR*', $i);
+ assertNativeType('*ERROR*', $i);
+ assertVariableCertainty(TrinaryLogic::createNo(), $i);
- assertType('10', $j);
- assertNativeType('10', $j);
+ assertType('0', $j);
+ assertNativeType('0', $j);
assertVariableCertainty(TrinaryLogic::createYes(), $j);
assertType('int', $a);
|
fyi, got the equivalent improvement for |
Keep them coming :) |
|
||
assertType('int<0, 1>', $c); | ||
assertNativeType('int', $c); | ||
assertVariableCertainty(TrinaryLogic::createYes(), $c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this should be maybe :(
Reverted for now. |
As reverted, can you reopen phpstan/phpstan#9550? |
I realized the issue - right now this behaviour is connected to polluteScopeWithLoopInitialAssignments but it might be a better idea to have its own |
Sounds like a good idea I guess. So you mean this could be brought back but only under that new flag? And if so - what about foreach? The behaviour change of phpstan/phpstan#8270 confused me too a bit hmm. |
Yeah, I guess so, let's try it :) |
Added a similar method on
Mutatingscope
asforeach
handling has it already. This should keep expressions in the scope we can safely keep while still removing the initial expressions whenpolluteScopeWithLoopInitialAssignments
is set tofalse
.Before, it was merging
$finalScope
with$scope
to get rid of initial expressions which has the downside of also getting rid of expressions that only exist in$finalScope
because e.g. the loop is iterating at least once and assigns a variable inside.Closes phpstan/phpstan#9550
Btw a similar thing seems to be going on with foreach and
polluteScopeWithAlwaysIterableForeach
set tofalse
.