Fix phpstan/phpstan#14455: missing has-offset via conditional type#5448
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Open
Fix phpstan/phpstan#14455: missing has-offset via conditional type#5448phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
- Added processBooleanNotSureSureConditionalTypes method to TypeSpecifier that creates conditional expression holders with sure-NOT-type conditions and sure-type results (cross-product of existing methods) - Called the new method in both BooleanAnd (falsey) and BooleanOr (truthy) conditional expression holder creation - New regression test in tests/PHPStan/Analyser/nsrt/bug-14455.php - Root cause: empty($arr['key']) && $type === 'filter' in an early return produced sure-NOT-types for $type and sure-types for $arr, but no existing method combined these to create the conditional holder needed for narrowing
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 an early return guard combines
empty($arr['key'])with a variable comparison via&&, PHPStan failed to narrow the array type inside a subsequent branch that checked the same variable. For example:PHPStan reported
array<string, mixed>instead ofnon-empty-array<string, mixed>&hasOffset('field').Changes
processBooleanNotSureSureConditionalTypes()method insrc/Analyser/TypeSpecifier.php— a cross-product of the existingprocessBooleanNotSureConditionalTypes(conditions) andprocessBooleanSureConditionalTypes(results) methodsBooleanAnd(falsey context) andBooleanOr(truthy context) conditional expression holder creationRoot cause
The
TypeSpecifiercreates conditional expression holders to express relationships like "when variable X has type T, then variable Y has type U". These holders are checked when entering branches.For
empty($arr['field']) && $type === 'filter'in the falsey context (after early return):empty()side produces sure types for$arr(intersect withHasOffsetType('field'))$type === 'filter'side produces sure-NOT-types for$type(remove'filter')The existing methods only created holders from matching kinds: sure-type conditions with sure-type results (
processBooleanSureConditionalTypes), or sure-NOT-type conditions with sure-NOT-type results (processBooleanNotSureConditionalTypes). The cross-product case — sure-NOT-type conditions with sure-type results — was missing. This meant no holder was created to express "when$typeis'filter', then$arrhashasOffset('field')".Test
Added
tests/PHPStan/Analyser/nsrt/bug-14455.php— verifies that afterif (empty($aggregation['field']) && $type === 'filter') { return; }, checkingif ($type === 'filter')correctly narrows$aggregationtonon-empty-array<string, mixed>&hasOffset('field').Fixes phpstan/phpstan#14455