Skip to content

Commit 8734057

Browse files
committed
Fix generalizing constant arrays when the array is getting smaller
1 parent cc6c200 commit 8734057

File tree

7 files changed

+55
-4
lines changed

7 files changed

+55
-4
lines changed

src/Analyser/MutatingScope.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -5045,7 +5045,10 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
50455045
} else {
50465046
$constantArraysA = TypeCombinator::union(...$constantArrays['a']);
50475047
$constantArraysB = TypeCombinator::union(...$constantArrays['b']);
5048-
if ($constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType())) {
5048+
if (
5049+
$constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType())
5050+
&& $constantArraysA->getArraySize()->equals($constantArraysB->getArraySize())
5051+
) {
50495052
$resultArrayBuilder = ConstantArrayTypeBuilder::createEmpty();
50505053
foreach (TypeUtils::flattenTypes($constantArraysA->getIterableKeyType()) as $keyType) {
50515054
$resultArrayBuilder->setOffsetValueType(
@@ -5065,7 +5068,11 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type
50655068
TypeCombinator::union(self::generalizeType($constantArraysA->getIterableKeyType(), $constantArraysB->getIterableKeyType(), $depth + 1)),
50665069
TypeCombinator::union(self::generalizeType($constantArraysA->getIterableValueType(), $constantArraysB->getIterableValueType(), $depth + 1)),
50675070
);
5068-
if ($constantArraysA->isIterableAtLeastOnce()->yes() && $constantArraysB->isIterableAtLeastOnce()->yes()) {
5071+
if (
5072+
$constantArraysA->isIterableAtLeastOnce()->yes()
5073+
&& $constantArraysB->isIterableAtLeastOnce()->yes()
5074+
&& $constantArraysA->getArraySize()->getGreaterOrEqualType()->isSuperTypeOf($constantArraysB->getArraySize())->yes()
5075+
) {
50695076
$resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType());
50705077
}
50715078
if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) {

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

+1-1
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('array<1|2|3>&list', $x);
1717

1818
if ($x) {
1919
}

tests/PHPStan/Analyser/nsrt/bug7856.php

+1-1
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
}

tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,12 @@ public function testLastMatchArm(bool $reportAlwaysTrueInLastCondition, array $e
940940
$this->analyse([__DIR__ . '/data/strict-comparison-last-match-arm.php'], $expectedErrors);
941941
}
942942

943+
public function testBug8030(): void
944+
{
945+
$this->checkAlwaysTrueStrictComparison = true;
946+
$this->analyse([__DIR__ . '/data/bug-8030.php'], []);
947+
}
948+
943949
public function testBug8776Part1(): void
944950
{
945951
$this->checkAlwaysTrueStrictComparison = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Bug8030;
4+
5+
function (): ?string
6+
{
7+
$refs = range('a', 'e');
8+
9+
while (null !== $ref = array_shift($refs)) {
10+
if (random_int(0, 1) === 1) {
11+
return $ref;
12+
}
13+
}
14+
15+
return null;
16+
};

tests/PHPStan/Rules/Variables/EmptyRuleTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,12 @@ public function testBug9403(bool $treatPhpDocTypesAsCertain): void
230230
$this->analyse([__DIR__ . '/data/bug-9403.php'], []);
231231
}
232232

233+
public function testBug12658(): void
234+
{
235+
$this->treatPhpDocTypesAsCertain = true;
236+
$this->strictUnnecessaryNullsafePropertyFetch = false;
237+
238+
$this->analyse([__DIR__ . '/data/bug-12658.php'], []);
239+
}
240+
233241
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug12658;
4+
5+
function (): void {
6+
$ads = ['inline_1', 'inline_2', 'inline_3', 'inline_4'];
7+
$paragraphs = ['a', 'b', 'c', 'd', 'f'];
8+
9+
foreach ($paragraphs as $key => $paragraph) {
10+
if (!empty($ads)) {
11+
$ad = array_shift($ads);
12+
}
13+
}
14+
};

0 commit comments

Comments
 (0)