Skip to content

Commit 598eaaa

Browse files
POC
1 parent d7d28b9 commit 598eaaa

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

src/Type/Constant/ConstantArrayTypeBuilder.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,16 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
110110
if ($offsetType === null) {
111111
$newAutoIndexes = $optional ? $this->nextAutoIndexes : [];
112112
$hasOptional = false;
113+
$existingMaxIndex = -1;
113114
foreach ($this->keyTypes as $i => $keyType) {
114115
if (!$keyType instanceof ConstantIntegerType) {
115116
continue;
116117
}
117118

119+
if ($keyType->getValue() > $existingMaxIndex) {
120+
$existingMaxIndex = $keyType->getValue();
121+
}
122+
118123
if (!in_array($keyType->getValue(), $this->nextAutoIndexes, true)) {
119124
continue;
120125
}
@@ -153,6 +158,10 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
153158
$this->optionalKeys[] = count($this->keyTypes) - 1;
154159
}
155160

161+
if ($max < 0 || $max > $existingMaxIndex + 1) {
162+
$this->isList = $this->isList->and($optional || $hasOptional ? TrinaryLogic::createMaybe() : TrinaryLogic::createNo());
163+
}
164+
156165
if (
157166
!$this->disableArrayDegradation
158167
&& count($this->keyTypes) > self::ARRAY_COUNT_LIMIT
@@ -199,12 +208,14 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
199208
$offsetValue = $offsetType->getValue();
200209
if ($offsetValue >= 0) {
201210
if ($offsetValue > $min) {
202-
if ($offsetValue <= $max) {
211+
if ($offsetValue <= $max || $optional) {
203212
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
204213
} else {
205214
$this->isList = TrinaryLogic::createNo();
206215
}
207216
}
217+
} elseif ($optional) {
218+
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
208219
} else {
209220
$this->isList = TrinaryLogic::createNo();
210221
}
@@ -221,6 +232,8 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
221232
$this->nextAutoIndexes[] = $newAutoIndex;
222233
}
223234
}
235+
} elseif ($optional) {
236+
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
224237
} else {
225238
$this->isList = TrinaryLogic::createNo();
226239
}
@@ -285,11 +298,17 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
285298
}
286299
}
287300

288-
$this->isList = TrinaryLogic::createNo();
301+
if ($optional) {
302+
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
303+
} else {
304+
$this->isList = TrinaryLogic::createNo();
305+
}
289306
}
290307

291308
if ($offsetType === null) {
292309
$offsetType = TypeCombinator::union(...array_map(static fn (int $index) => new ConstantIntegerType($index), $this->nextAutoIndexes));
310+
} elseif ($optional) {
311+
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
293312
} else {
294313
$this->isList = TrinaryLogic::createNo();
295314
}

tests/PHPStan/Analyser/nsrt/array-is-list-unset.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function () {
1919
assertType('true', array_is_list($a));
2020
unset($a[2]);
2121
assertType('array{1, 2}', $a);
22-
assertType('false', array_is_list($a));
22+
assertType('true', array_is_list($a));
2323
$a[] = 4;
2424
assertType('array{0: 1, 1: 2, 3: 4}', $a);
2525
assertType('false', array_is_list($a));

0 commit comments

Comments
 (0)