Fix phpstan/phpstan#6705: Solve in_array() once and for all#5380
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Open
Fix phpstan/phpstan#6705: Solve in_array() once and for all#5380phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
…to InArrayFunctionTypeSpecifyingExtension
Remove the ~100-line special-case in_array handling from ImpossibleCheckTypeHelper
and handle all impossibility detection entirely within the type-specifying extension
using the rootExpr mechanism.
The extension now returns:
- ConstFetch('true') rootExpr when in_array is guaranteed to always return true
- ConstFetch('false') rootExpr when types are incompatible (always false)
- ConstFetch('__PHPSTAN_FAUX_CONSTANT') rootExpr for indeterminate cases
This approach bypasses the sureTypes-based detection in ImpossibleCheckTypeHelper,
which suffered from scope leakage issues (e.g., ClassConstFetch expressions for
enum cases being marked as "specified" by prior in_array calls in the same scope).
Fixes phpstan/phpstan#6705
Also fixes detection of previously-undetected cases:
- in_array(Enum::A, non-empty-array<Enum::A>, false/true) now correctly reports
"always true" when enum type guarantees a match
- in_array(Enum::B, array<Enum::A>, false/true) now correctly reports
"always false" when enum types are incompatible
- in_array('foo', ['foo', 'bar']) without strict param is now correctly narrowed
to return type `true` (string-to-string comparison is equivalent to strict)
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
in_arrayhandling fromImpossibleCheckTypeHelper(lines 98-198) as requested in Solve in_array() once and for all phpstan#6705in_arrayimpossibility detection entirely withinInArrayFunctionTypeSpecifyingExtensionusing therootExprmechanismrootExprfor strict in_array calls, usingConstFetch('true')/ConstFetch('false')/ConstFetch('__PHPSTAN_FAUX_CONSTANT')to signal always-true, always-false, or indeterminate results respectivelyChanges
src/Type/Php/InArrayFunctionTypeSpecifyingExtension.phpdetermineRootExpr()method that checks type compatibility and guaranteed containmentisGuaranteedToContainNeedle()method for always-true detection (handles both ConstantArrayType with non-optional keys and generic arrays with single finite value type)computeNeedleNarrowingType()method for false-context needle type narrowingrootExprto the non-strict path to prevent false positivesinstanceof ConstantArrayTypewithgetConstantArrays()per PHPStan conventionssrc/Rules/Comparison/ImpossibleCheckTypeHelper.phpin_arrayspecial-case block (~100 lines)ConstantArrayType,NeverType)Test changes
tests/PHPStan/Rules/Comparison/data/bug-6705.phploose-comparison-against-enums.php)binary.phpassertion:in_array('foo', ['foo', 'bar'])now correctly inferred astrueinstead ofboolinstanceof ConstantArrayTypeignoresTest plan
make tests- all 11722 tests passmake phpstan- no errorsmake cs-fix- no violationsmake name-collision- pre-existing failure (unrelated pipe-operator syntax)