Skip to content

Commit 13b7dfa

Browse files
committed
Fix generalizing constant arrays when the array is getting smaller
1 parent c27879c commit 13b7dfa

File tree

3 files changed

+12
-4
lines changed

3 files changed

+12
-4
lines changed

src/Analyser/MutatingScope.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
use function usort;
167167
use const PHP_INT_MAX;
168168
use const PHP_INT_MIN;
169+
use const PHP_VERSION_ID;
169170

170171
final class MutatingScope implements Scope
171172
{
@@ -5138,7 +5139,10 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
51385139
} else {
51395140
$constantArraysA = TypeCombinator::union(...$constantArrays['a']);
51405141
$constantArraysB = TypeCombinator::union(...$constantArrays['b']);
5141-
if ($constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType())) {
5142+
if (
5143+
$constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType())
5144+
&& $constantArraysA->getArraySize()->equals($constantArraysB->getArraySize())
5145+
) {
51425146
$resultArrayBuilder = ConstantArrayTypeBuilder::createEmpty();
51435147
foreach (TypeUtils::flattenTypes($constantArraysA->getIterableKeyType()) as $keyType) {
51445148
$resultArrayBuilder->setOffsetValueType(
@@ -5158,7 +5162,11 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
51585162
TypeCombinator::union(self::generalizeType($constantArraysA->getIterableKeyType(), $constantArraysB->getIterableKeyType(), $depth + 1)),
51595163
TypeCombinator::union(self::generalizeType($constantArraysA->getIterableValueType(), $constantArraysB->getIterableValueType(), $depth + 1)),
51605164
);
5161-
if ($constantArraysA->isIterableAtLeastOnce()->yes() && $constantArraysB->isIterableAtLeastOnce()->yes()) {
5165+
if (
5166+
$constantArraysA->isIterableAtLeastOnce()->yes()
5167+
&& $constantArraysB->isIterableAtLeastOnce()->yes()
5168+
&& $constantArraysA->getArraySize()->getGreaterOrEqualType(new PhpVersion(PHP_VERSION_ID))->isSuperTypeOf($constantArraysB->getArraySize())->yes()
5169+
) {
51625170
$resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType());
51635171
}
51645172
if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) {

tests/PHPStan/Analyser/nsrt/bug-1021.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function foobar() {
1313
}
1414
}
1515

16-
assertType('array{0?: int<1, max>, 1?: 2|3, 2?: 3}', $x);
16+
assertType('list<1|2|3>', $x);
1717

1818
if ($x) {
1919
}

tests/PHPStan/Analyser/nsrt/bug7856.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function doFoo() {
1010
$endDate = new DateTimeImmutable('+1year');
1111

1212
do {
13-
assertType("array{'+1week', '+1months', '+6months', '+17months'}|array{0: literal-string&lowercase-string&non-falsy-string, 1?: literal-string&lowercase-string&non-falsy-string, 2?: '+17months'}", $intervals);
13+
assertType("list<literal-string&lowercase-string&non-falsy-string>", $intervals);
1414
$periodEnd = $periodEnd->modify(array_shift($intervals));
1515
} while (count($intervals) > 0 && $periodEnd->format('U') < $endDate);
1616
}

0 commit comments

Comments
 (0)