Skip to content

Commit 4ec3540

Browse files
committed
Improve ConstantArrayType::sliceArray() with non constant integer args
1 parent 488b65f commit 4ec3540

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

src/Type/Constant/ConstantArrayType.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,8 +939,23 @@ public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $pre
939939
return $this;
940940
}
941941

942-
$offset = $offsetType instanceof ConstantIntegerType ? $offsetType->getValue() : 0;
943-
$length = $lengthType instanceof ConstantIntegerType ? $lengthType->getValue() : $keyTypesCount;
942+
$offset = $offsetType instanceof ConstantIntegerType ? $offsetType->getValue() : null;
943+
944+
if ($lengthType instanceof ConstantIntegerType) {
945+
$length = $lengthType->getValue();
946+
} elseif ($lengthType->isNull()->yes()) {
947+
$length = $keyTypesCount;
948+
} else {
949+
$length = null;
950+
}
951+
952+
if ($offset === null || $length === null) {
953+
$builder = ConstantArrayTypeBuilder::createFromConstantArray($this);
954+
$builder->degradeToGeneralArray();
955+
956+
return $builder->getArray()
957+
->sliceArray($offsetType, $lengthType, $preserveKeys);
958+
}
944959

945960
if ($length < 0) {
946961
// Negative lengths prevent access to the most right n elements

tests/PHPStan/Analyser/nsrt/array-slice.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function constantArrays(array $arr): void
4343
/** @var array{17: 'foo', b: 'bar', 19: 'baz'} $arr */
4444
assertType('array{b: \'bar\', 0: \'baz\'}', array_slice($arr, 1, 2));
4545
assertType('array{b: \'bar\', 19: \'baz\'}', array_slice($arr, 1, 2, true));
46+
assertType('array<17|19|\'b\', \'bar\'|\'baz\'|\'foo\'>', array_slice($arr, rand(0, 1) ? 0 : 1, rand(0, 1) ? 0 : 1));
4647

4748
/** @var array{17: 'foo', 19: 'bar', 21: 'baz'}|array{foo: 17, bar: 19, baz: 21} $arr */
4849
assertType('array{\'bar\', \'baz\'}|array{bar: 19, baz: 21}', array_slice($arr, 1, 2));

0 commit comments

Comments
 (0)