Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c1aeb64

Browse files
RobertMeondrejmirtes
authored andcommitted
Do not generalize big array when combined with empty array
Fixes phpstan/phpstan#10834
1 parent e74cd7c commit c1aeb64

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

‎src/Type/TypeCombinator.php‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,12 +664,19 @@ private static function processArrayTypes(array $arrayTypes): array
664664
$valueTypesForGeneralArray = [];
665665
$generalArrayOccurred = false;
666666
$constantKeyTypesNumbered = [];
667+
$filledArrays = 0;
668+
$overflowed = false;
667669

668670
/** @var int|float $nextConstantKeyTypeIndex */
669671
$nextConstantKeyTypeIndex = 1;
670672

671673
foreach ($arrayTypes as $arrayType) {
672-
if ($generalArrayOccurred || !$arrayType->isConstantArray()->yes()) {
674+
$isConstantArray = $arrayType->isConstantArray()->yes();
675+
if (!$isConstantArray || !$arrayType->isIterableAtLeastOnce()->no()) {
676+
$filledArrays++;
677+
}
678+
679+
if ($generalArrayOccurred || !$isConstantArray) {
673680
foreach ($arrayType->getArrays() as $type) {
674681
$keyTypesForGeneralArray[] = $type->getIterableKeyType();
675682
$valueTypesForGeneralArray[] = $type->getItemType();
@@ -693,13 +700,14 @@ private static function processArrayTypes(array $arrayTypes): array
693700
$nextConstantKeyTypeIndex *= 2;
694701
if (!is_int($nextConstantKeyTypeIndex)) {
695702
$generalArrayOccurred = true;
703+
$overflowed = true;
696704
continue 2;
697705
}
698706
}
699707
}
700708
}
701709

702-
if ($generalArrayOccurred) {
710+
if ($generalArrayOccurred && (!$overflowed || $filledArrays > 1)) {
703711
$scopes = [];
704712
$useTemplateArray = true;
705713
foreach ($arrayTypes as $arrayType) {

‎tests/PHPStan/Analyser/NodeScopeResolverTest.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,7 @@ public function dataFileAsserts(): iterable
14611461
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10468.php');
14621462
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6613.php');
14631463
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10187.php');
1464+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10834.php');
14641465
}
14651466

14661467
/**
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @return array{1: string, 2: int, 3: bool, 4: string, 5: int, 6: bool, 7: string, 8: int, 9: bool, 10: string, 11: int, 12: bool, 13: string, 14: int, 15: bool, 16: string, 17: int, 18: bool, 19: string, 20: int, 21: bool, 22: string, 23: int, 24: bool, 25: string, 26: int, 27: bool, 28: string, 29: int, 30: bool, 31: string, 32: int, 33: bool, 34: string, 35: int, 36: bool, 37: string, 38: int, 39: bool, 40: string, 41: int, 42: bool, 43: string, 44: int, 45: bool, 46: string, 47: int, 48: bool, 49: string, 50: int, 51: bool, 52: string, 53: int, 54: bool, 55: string, 56: int, 57: bool, 58: string, 59: int, 60: bool, 61: string, 62: int, 63: bool, 64: float}|null
9+
*/
10+
function returnArrayOrNull()
11+
{
12+
return null;
13+
}
14+
15+
function test(): void {
16+
$arrayOrNull = returnArrayOrNull();
17+
18+
assertType('array{1: string, 2: int, 3: bool, 4: string, 5: int, 6: bool, 7: string, 8: int, 9: bool, 10: string, 11: int, 12: bool, 13: string, 14: int, 15: bool, 16: string, 17: int, 18: bool, 19: string, 20: int, 21: bool, 22: string, 23: int, 24: bool, 25: string, 26: int, 27: bool, 28: string, 29: int, 30: bool, 31: string, 32: int, 33: bool, 34: string, 35: int, 36: bool, 37: string, 38: int, 39: bool, 40: string, 41: int, 42: bool, 43: string, 44: int, 45: bool, 46: string, 47: int, 48: bool, 49: string, 50: int, 51: bool, 52: string, 53: int, 54: bool, 55: string, 56: int, 57: bool, 58: string, 59: int, 60: bool, 61: string, 62: int, 63: bool, 64: float}|null', $arrayOrNull);
19+
assertType('array{}|array{1: string, 2: int, 3: bool, 4: string, 5: int, 6: bool, 7: string, 8: int, 9: bool, 10: string, 11: int, 12: bool, 13: string, 14: int, 15: bool, 16: string, 17: int, 18: bool, 19: string, 20: int, 21: bool, 22: string, 23: int, 24: bool, 25: string, 26: int, 27: bool, 28: string, 29: int, 30: bool, 31: string, 32: int, 33: bool, 34: string, 35: int, 36: bool, 37: string, 38: int, 39: bool, 40: string, 41: int, 42: bool, 43: string, 44: int, 45: bool, 46: string, 47: int, 48: bool, 49: string, 50: int, 51: bool, 52: string, 53: int, 54: bool, 55: string, 56: int, 57: bool, 58: string, 59: int, 60: bool, 61: string, 62: int, 63: bool, 64: float}', $arrayOrNull ?? []);
20+
assertType('array{}|array{1: string, 2: int, 3: bool, 4: string, 5: int, 6: bool, 7: string, 8: int, 9: bool, 10: string, 11: int, 12: bool, 13: string, 14: int, 15: bool, 16: string, 17: int, 18: bool, 19: string, 20: int, 21: bool, 22: string, 23: int, 24: bool, 25: string, 26: int, 27: bool, 28: string, 29: int, 30: bool, 31: string, 32: int, 33: bool, 34: string, 35: int, 36: bool, 37: string, 38: int, 39: bool, 40: string, 41: int, 42: bool, 43: string, 44: int, 45: bool, 46: string, 47: int, 48: bool, 49: string, 50: int, 51: bool, 52: string, 53: int, 54: bool, 55: string, 56: int, 57: bool, 58: string, 59: int, 60: bool, 61: string, 62: int, 63: bool, 64: float}|null', rand() ? $arrayOrNull : []);
21+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /