Skip to content

Commit af5ba63

Browse files
committed
Optimize range() dynamic return type extension for big arrays
1 parent 030b4f5 commit af5ba63

3 files changed

Lines changed: 15 additions & 4 deletions

File tree

src/Type/Php/RangeFunctionReturnTypeExtension.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PHPStan\Analyser\Scope;
77
use PHPStan\Reflection\FunctionReflection;
88
use PHPStan\Reflection\ParametersAcceptorSelector;
9+
use PHPStan\Type\Accessory\NonEmptyArrayType;
910
use PHPStan\Type\ArrayType;
1011
use PHPStan\Type\BenevolentUnionType;
1112
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
@@ -14,6 +15,7 @@
1415
use PHPStan\Type\Constant\ConstantStringType;
1516
use PHPStan\Type\FloatType;
1617
use PHPStan\Type\IntegerType;
18+
use PHPStan\Type\IntersectionType;
1719
use PHPStan\Type\StringType;
1820
use PHPStan\Type\Type;
1921
use PHPStan\Type\TypeCombinator;
@@ -60,11 +62,20 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
6062
continue;
6163
}
6264

63-
$arrayBuilder = ConstantArrayTypeBuilder::createEmpty();
6465
$rangeValues = range($startConstant->getValue(), $endConstant->getValue(), $stepConstant->getValue());
6566
if (count($rangeValues) > self::RANGE_LENGTH_THRESHOLD) {
66-
$arrayBuilder->degradeToGeneralArray();
67+
return new IntersectionType([
68+
new ArrayType(
69+
new IntegerType(),
70+
TypeCombinator::union(
71+
$startConstant->generalize(),
72+
$endConstant->generalize()
73+
)
74+
),
75+
new NonEmptyArrayType(),
76+
]);
6777
}
78+
$arrayBuilder = ConstantArrayTypeBuilder::createEmpty();
6879
foreach ($rangeValues as $value) {
6980
$arrayBuilder->setOffsetValueType(null, $scope->getTypeFromValue($value));
7081
}

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6100,7 +6100,7 @@ public function dataRangeFunction(): array
61006100
'range(3, -1)',
61016101
],
61026102
[
6103-
'array<int, int>',
6103+
'array<int, int>&nonEmpty',
61046104
'range(0, 50)',
61056105
],
61066106
];

tests/PHPStan/Analyser/data/bug-4207.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
use function PHPStan\Analyser\assertType;
66

77
function (): void {
8-
assertType('array<int, int>', range(1, 10000));
8+
assertType('array<int, int>&nonEmpty', range(1, 10000));
99
};

0 commit comments

Comments
 (0)