fix: generic sealed class-string match exhaustiveness for ::class comparisons#5367
Closed
mhert wants to merge 1 commit intophpstan:2.1.xfrom
Closed
fix: generic sealed class-string match exhaustiveness for ::class comparisons#5367mhert wants to merge 1 commit intophpstan:2.1.xfrom
mhert wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
Member
|
Please open a bug report first. |
GenericClassStringType::tryRemove() passed the GenericObjectType directly to TypeCombinator::remove(), but GenericObjectType::isSuperTypeOf(plain ObjectType) returns Maybe rather than Yes, so the removal was silently skipped. Strips the generic parameters before delegating to TypeCombinator::remove() so the existing sealed subtraction logic in ObjectType::changeSubtractedType() can handle it.
74421a4 to
2092cf3
Compare
Member
|
Superseded by #5369 |
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
GenericClassStringType::tryRemove()did not correctly handle@phpstan-sealedhierarchies when the sealed class has generic type parameters (@template). Match expressions on$foo::classfalsely reported "Match expression does not handle remaining values" even when all allowed subtypes were covered.Follow-up to #5305
Motivation
The fix in #5305 passed
$generic(e.g.FooCov<string>) directly toTypeCombinator::remove(), which couldn't correctly subtract sealed subtypes from a generic type. This meant sealed exhaustiveness still failed when the sealed class had template parameters.Changes
src/Type/Generic/GenericClassStringType.php— In the sealed-aware removal path oftryRemove(), construct a plainObjectType(with the existing subtracted type carried over) instead of passing the generic type directly toTypeCombinator::remove(). This allows sealed subtraction to work correctly regardless of template parameters.Test Cases
tests/PHPStan/Rules/Comparison/data/match-generic-sealed-class-string.php— Two scenarios:FooCov<T>sealed toBarCov|BazCov) — exhaustive match produces no errorFooInv<T>sealed toBarInv|BazInv) — exhaustive match produces no errortests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php— AddedtestGenericSealedClassStringMatch()rule test method.