Skip to content

Commit b3fe1bb

Browse files
committed
Skip "might not exist" report for string types with integer offsets in union decomposition check
- In NonexistentOffsetInArrayDimFetchCheck, the reportMaybes decomposition loop flattens union types and checks each member individually. When a constant string member (e.g. '') returns "no" for an integer offset (e.g. 0), it incorrectly triggers "might not exist" even though the union-level check correctly returns "maybe". - Skip the report when innerType is a string and innerDimType is an integer, since string offset validity is length-dependent and users typically guard with length checks through variables that PHPStan cannot track. - The fix does not affect: definite "does not exist" errors (caught earlier), non-integer offsets on strings (objects, floats, strings still report), or array offset checks (completely unaffected). - Probed analogous cases: non-integer dim types on strings, array offset decomposition, ArrayDestructuringRule (shares the same check) — all already correct.
1 parent dfe0c76 commit b3fe1bb

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ public function check(
126126
if (
127127
$innerType->hasOffsetValueType($innerDimType)->no()
128128
) {
129+
if ($innerType->isString()->yes() && $innerDimType->isInteger()->yes()) {
130+
continue;
131+
}
129132
$report = true;
130133
break 2;
131134
}

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,11 @@ public function testBug9240(): void
13261326
$this->analyse([__DIR__ . '/data/bug-9240.php'], []);
13271327
}
13281328

1329+
public function testBug13688(): void
1330+
{
1331+
$this->analyse([__DIR__ . '/data/bug-13688.php'], []);
1332+
}
1333+
13291334
#[RequiresPhp('>= 8.4.0')]
13301335
public function testArrayFindKeyExisting(): void
13311336
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug13688;
4+
5+
$inputs = [ '', ':' ];
6+
7+
foreach ( $inputs as $input )
8+
{
9+
$inputLen = \strlen($input);
10+
$hasTrailingColon = $inputLen > 0 && $input[$inputLen-1] === ':';
11+
echo $hasTrailingColon ? "{$input} has trailing colon\n" : "{$input} does not have trailing colon\n";
12+
}
13+
14+
function directComparison(): void
15+
{
16+
/** @var 'a'|'abc' $s */
17+
$s = 'a';
18+
echo $s[0];
19+
}

0 commit comments

Comments
 (0)