Skip to content

Fix phpstan/phpstan#4296: BleedingEdge: Offset '1234' on array<string, Test>&nonEmpty in isset() does not exist.#5174

Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-kz2bn6x
Closed

Fix phpstan/phpstan#4296: BleedingEdge: Offset '1234' on array<string, Test>&nonEmpty in isset() does not exist.#5174
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-kz2bn6x

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

PHPStan incorrectly reported "Offset '1234' on array<string, Test>&nonEmpty in isset() does not exist" when checking a numeric string key against a string-keyed array. This fix ensures the original offset type (before toArrayKey() conversion) is also checked against the array's key type.

Changes

  • src/Type/ArrayType.php: In both hasOffsetValueType() and getOffsetValueType(), added a check that also compares the original offset type (before toArrayKey() conversion) against the array's key type. This prevents numeric string keys like '1234' from being falsely rejected when the array has string keys.
  • tests/PHPStan/Rules/Variables/data/bug-4296.php: New regression test reproducing the issue.
  • tests/PHPStan/Rules/Variables/IssetRuleTest.php: Added testBug4296 method.
  • tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php: Removed false positive expectation for '0' on array<string, string> (same root cause).

Root cause

ArrayType::hasOffsetValueType() calls toArrayKey() on the offset type, which converts numeric strings (e.g., '1234') to their integer equivalents (e.g., 1234) per PHP semantics. The subsequent check $this->getKeyType()->isSuperTypeOf($offsetType) then compares StringType against ConstantIntegerType(1234), which returns no. The fix preserves the original offset type and checks it against the key type as well — since '1234' IS a string and the key type IS string, the offset should not be rejected.

Test

Added tests/PHPStan/Rules/Variables/data/bug-4296.php that reproduces the exact scenario from the issue: building an array<string, Test> via a loop, then checking isset($map[$value]) where $value is the numeric string '1234'. The test expects no errors.

Fixes phpstan/phpstan#4296

… isset()

- In ArrayType::hasOffsetValueType and getOffsetValueType, toArrayKey() converts
  numeric strings like '1234' to integers, losing the original string type info
- Added check against original offset type before toArrayKey() conversion so that
  a string offset on a string-keyed array is not incorrectly rejected
- Updated NonexistentOffsetInArrayDimFetchRuleTest to reflect that '0' on
  array<string, string> is no longer a false positive
- New regression test in tests/PHPStan/Rules/Variables/data/bug-4296.php

Closes phpstan/phpstan#4296
@VincentLanglet
Copy link
Copy Markdown
Contributor

I'm not sure we should do anything until phpstan/phpstan#6847 is fixed
cf phpstan/phpstan#4296 (comment)

@staabm
Copy link
Copy Markdown
Contributor

staabm commented Mar 27, 2026

closing as a lot has changed since than and this is related to how int-string keys behave

@staabm staabm closed this Mar 27, 2026
@staabm staabm deleted the create-pull-request/patch-kz2bn6x branch March 27, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants