Skip to content

Commit fe595cb

Browse files
committed
ArrayType - setting new offset with [] on array with constant-integer offset will add one to the offset
1 parent 7d8742a commit fe595cb

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

src/Type/ArrayType.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,17 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
455455
if ($isKeyTypeInteger->no()) {
456456
$offsetType = new IntegerType();
457457
} elseif ($isKeyTypeInteger->yes()) {
458-
$offsetType = $this->keyType;
458+
/** @var list<ConstantIntegerType> $constantScalars */
459+
$constantScalars = $this->keyType->getConstantScalarTypes();
460+
if (count($constantScalars) > 0) {
461+
foreach ($constantScalars as $constantScalar) {
462+
$constantScalars[] = ConstantTypeHelper::getTypeFromValue($constantScalar->getValue() + 1);
463+
}
464+
465+
$offsetType = TypeCombinator::union(...$constantScalars);
466+
} else {
467+
$offsetType = $this->keyType;
468+
}
459469
} else {
460470
$integerTypes = [];
461471
TypeTraverser::map($this->keyType, static function (Type $type, callable $traverse) use (&$integerTypes): Type {

tests/PHPStan/Rules/Variables/IssetRuleTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -483,4 +483,12 @@ public function testBug10064(): void
483483
$this->analyse([__DIR__ . '/data/bug-10064.php'], []);
484484
}
485485

486+
public function testBug9328(): void
487+
{
488+
$this->treatPhpDocTypesAsCertain = true;
489+
$this->strictUnnecessaryNullsafePropertyFetch = true;
490+
491+
$this->analyse([__DIR__ . '/data/bug-9328.php'], []);
492+
}
493+
486494
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Bug9328;
4+
5+
function (): void {
6+
$contents = file('foo.ini', FILE_IGNORE_NEW_LINES);
7+
if (false === $contents) {
8+
throw new \Exception('Failed to read file');
9+
}
10+
// Add section so that the last one is flushed:
11+
$contents[] = '[--]';
12+
$currentSection = '';
13+
$sections = [];
14+
$lines = [];
15+
foreach ($contents as $line) {
16+
if (
17+
str_starts_with($line, '[')
18+
&& str_ends_with($line, ']')
19+
&& strlen($line) > 2
20+
) {
21+
// flush previously collected section:
22+
if ($lines) {
23+
$sections[] = [
24+
'name' => $currentSection,
25+
'lines' => $lines,
26+
];
27+
}
28+
$currentSection = substr($line, 1, -1);
29+
$lines = [];
30+
}
31+
$lines[] = $line;
32+
}
33+
34+
if (isset($sections[1])) {
35+
echo "We have multiple remaining sections!\n";
36+
}
37+
};

0 commit comments

Comments
 (0)