Skip to content

Commit 9f829c3

Browse files
VincentLangletphpstan-bot
authored andcommitted
Fix array auto-index for negative keys on PHP 8.3+
- PHP 8.3 fixed an incomplete RFC implementation where $a[] after negative keys should use max_key+1, not 0 - Updated ConstantArrayTypeBuilder to account for this when computing nextAutoIndexes - Added regression test in tests/PHPStan/Analyser/nsrt/bug-10862.php Closes phpstan/phpstan#10862
1 parent 06ea1e1 commit 9f829c3

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/Type/Constant/ConstantArrayTypeBuilder.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type\Constant;
44

5+
use PHPStan\Reflection\PhpVersionStaticAccessor;
56
use PHPStan\ShouldNotHappenException;
67
use PHPStan\TrinaryLogic;
78
use PHPStan\Type\Accessory\AccessoryArrayListType;
@@ -209,7 +210,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
209210
$this->isList = TrinaryLogic::createNo();
210211
}
211212

212-
if ($offsetValue >= $max) {
213+
if (
214+
$offsetValue >= $max
215+
|| ($offsetValue < 0 && $max === 0 && PhpVersionStaticAccessor::getInstance()->getVersionId() >= 80300)
216+
) {
213217
/** @var int|float $newAutoIndex */
214218
$newAutoIndex = $offsetValue + 1;
215219
if (is_float($newAutoIndex)) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug10862;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
function () {
10+
$a = [];
11+
$a[-4] = 1;
12+
$a[] = 2;
13+
14+
assertType('array{-4: 1, -3: 2}', $a); // PHP 8.3+: next key after -4 is -3
15+
assertType('array{-4, -3}', array_keys($a));
16+
};
17+
18+
function () {
19+
$a = [];
20+
$a[-1] = 'x';
21+
$a[] = 'y';
22+
23+
assertType("array{-1: 'x', 0: 'y'}", $a); // PHP 8.3+: next key after -1 is 0
24+
assertType('array{-1, 0}', array_keys($a));
25+
};
26+
27+
function () {
28+
$a = [];
29+
$a[-10] = 'a';
30+
$a[-5] = 'b';
31+
$a[] = 'c';
32+
33+
assertType("array{-10: 'a', -5: 'b', -4: 'c'}", $a); // PHP 8.3+: next key after max(-10,-5)=-5 is -4
34+
assertType('array{-10, -5, -4}', array_keys($a));
35+
};
36+
37+
function () {
38+
$a = [];
39+
$a[-3] = 'a';
40+
$a[5] = 'b';
41+
$a[] = 'c';
42+
43+
assertType("array{-3: 'a', 5: 'b', 6: 'c'}", $a); // positive key dominates
44+
assertType('array{-3, 5, 6}', array_keys($a));
45+
};

0 commit comments

Comments
 (0)