[DeadCode] Keep type-assertion guard in BooleanAnd when right operand reuses the variable#8112
Closed
TomasVotruba wants to merge 1 commit into
Closed
[DeadCode] Keep type-assertion guard in BooleanAnd when right operand reuses the variable#8112TomasVotruba wants to merge 1 commit into
TomasVotruba wants to merge 1 commit into
Conversation
… reuses the variable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
RemoveAlwaysTrueIfConditionRectorstrips the left operand of a&&condition when it is "always true". For a type-assertion guard (is_string,is_array, ...) whose "always true" comes from a phpdoc-narrowed type, that type can be violated at runtime — and the right operand often depends on the guard.Reported from
spiral/framework(PrototypeBootloader::initRegistry), which had to skip the rule:PHPStan narrows
$shortcuttostring(an earlieris_array($shortcut) && isset($shortcut['resolve'])branch removes the array shape via the@psalm-type), sois_string()is "always true" and the rule removed it:A malformed (non-string) binding in user config then reaches
class_exists(array)→TypeError. Theis_string()guard exists precisely for that runtime case.Fix
In the
BooleanAndpath, keep the condition when the left operand is a type-assertion guard (is_string/is_array/is_int/...) whose argument variable is reused in the right operand. In that case the guard protects the right side, so it must not be dropped even if "always true" by declared types.When the guarded variable is not reused on the right, stripping still happens.
Fixtures
skip_type_guard_reused_in_boolean_and.php.inc(no-change) —is_object($o) && method_exists($o, ...). This was previously theboolean_and.php.incchange fixture; the guard is now kept.boolean_and_guard_not_reused.php.inc(change) —is_object($o) && $flagstill strips, since$ois not reused.