Fix #5610: Match integer comparision#5085
Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Closed
Conversation
- Added resolveComplementaryComparison() method to MutatingScope that checks if the complement of a comparison expression has a stored type in the scope - When resolving $a >= $b, if $a < $b is already stored as false (or true), the complement is returned, allowing match(true) to detect exhaustive arms - Handles all four comparison pairs: < / >=, <= / >, > / <=, >= / < - New regression test in tests/PHPStan/Rules/Comparison/data/bug-5610.php Closes phpstan/phpstan#5610
Contributor
VincentLanglet
left a comment
There was a problem hiding this comment.
This need more tests, like
- does the second case is reported as always true (and people should use default)
- how is handled:
Contributor
VincentLanglet
left a comment
There was a problem hiding this comment.
I tried and this is too specific, more case should be handled
https://phpstan.org/r/9b3cc36b-6df2-4db3-83b3-cadf8850c6b8
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.
Summary
When using
match(true)with complementary integer comparisons like$bar < $bazand$bar >= $baz, PHPStan incorrectly reported "Match expression does not handle remaining value: true" even though the two arms cover all possible cases.Changes
resolveComplementaryComparison()method tosrc/Analyser/MutatingScope.phpthat checks stored expression types for complementary comparisonsMutatingScope::resolveType()to use this method before computing comparison results from operand typestests/PHPStan/Rules/Comparison/data/bug-5610.phpcovering all four complement pairs (</>=,>/<=,<=/>,>=/<)testBug5610()intests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.phpRoot cause
When
match(true)processes arms sequentially, after the first arm ($bar < $baz), the scope stores$bar < $baz → falseviafilterByFalseyValue. However, when resolving the second arm's condition$bar >= $baz,MutatingScope::resolveType()computed the result purely from the operand types (int >= int→maybe→bool), without checking if the complementary expression$bar < $bazalready had a stored constant boolean type. SincegetType($bar >= $baz)returnedboolinstead oftrue, the match was not detected as exhaustive.The fix adds a complement check: when resolving
$a >= $b, it looks up$a < $bin the scope's stored expression types. If the complement is stored asfalse, the comparison returnstrue(and vice versa). This allows the match arm processing to correctly identify the second arm as always-true, making the match exhaustive.Test
The regression test covers four functions, each with a
match(true)using a different pair of complementary comparisons (</>=,>/<=,<=/>,>=/<). All are expected to produce no errors (empty expected errors array).Fixes phpstan/phpstan#5610