From 2949e3da36cd3a6e691fbe262a513a37b69d1dcf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 03:48:41 +0000 Subject: [PATCH] Fix false positive "offset might not exist" for string offset in union - Skip "might not exist" report for string types with integer offsets in NonexistentOffsetInArrayDimFetchCheck decomposition check - When a union of constant strings (e.g. ''|':') is accessed with a valid integer offset, the decomposition incorrectly flagged it because one member (empty string) returned "no" for the offset - The union-level check already correctly returns "maybe" for such cases - New regression test in tests/PHPStan/Rules/Arrays/data/bug-13688.php Closes https://github.com/phpstan/phpstan/issues/13688 --- .../Arrays/NonexistentOffsetInArrayDimFetchCheck.php | 3 +++ .../NonexistentOffsetInArrayDimFetchRuleTest.php | 5 +++++ tests/PHPStan/Rules/Arrays/data/bug-13688.php | 12 ++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 tests/PHPStan/Rules/Arrays/data/bug-13688.php diff --git a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php index 263a62aebf9..08e0794d0ca 100644 --- a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php +++ b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php @@ -126,6 +126,9 @@ public function check( if ( $innerType->hasOffsetValueType($innerDimType)->no() ) { + if ($innerType->isString()->yes() && $innerDimType->isInteger()->yes()) { + continue; + } $report = true; break 2; } diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index 7def992a257..d61948406c7 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -1277,4 +1277,9 @@ public function testBug14308(): void $this->analyse([__DIR__ . '/data/bug-14308.php'], []); } + public function testBug13688(): void + { + $this->analyse([__DIR__ . '/data/bug-13688.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Arrays/data/bug-13688.php b/tests/PHPStan/Rules/Arrays/data/bug-13688.php new file mode 100644 index 00000000000..19a7d57a7af --- /dev/null +++ b/tests/PHPStan/Rules/Arrays/data/bug-13688.php @@ -0,0 +1,12 @@ + 0 && $input[$inputLen-1] === ':'; + echo $hasTrailingColon ? "{$input} has trailing colon\n" : "{$input} does not have trailing colon\n"; +}