Skip to content

Commit

Permalink
range() with float step should return an array of floats
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored Sep 19, 2024
1 parent 988f058 commit 7a6a0fa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/Type/Php/RangeFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,17 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
}

if (count($rangeValues) > self::RANGE_LENGTH_THRESHOLD) {
if ($startConstant instanceof ConstantIntegerType && $endConstant instanceof ConstantIntegerType) {
if (
$startConstant instanceof ConstantIntegerType
&& $endConstant instanceof ConstantIntegerType
&& $stepConstant instanceof ConstantIntegerType
) {
if ($startConstant->getValue() > $endConstant->getValue()) {
$tmp = $startConstant;
$startConstant = $endConstant;
$endConstant = $tmp;
}

return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(
new ArrayType(
new IntegerType(),
Expand All @@ -94,12 +99,23 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
));
}

if ($stepType->isFloat()->yes()) {
return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(
new ArrayType(
new IntegerType(),
new FloatType(),
),
new NonEmptyArrayType(),
));
}

return AccessoryArrayListType::intersectWith(TypeCombinator::intersect(
new ArrayType(
new IntegerType(),
TypeCombinator::union(
$startConstant->generalize(GeneralizePrecision::moreSpecific()),
$endConstant->generalize(GeneralizePrecision::moreSpecific()),
$stepType->generalize(GeneralizePrecision::moreSpecific()),
),
),
new NonEmptyArrayType(),
Expand Down
24 changes: 24 additions & 0 deletions tests/PHPStan/Analyser/nsrt/bug-11692.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Bug11692;

use function PHPStan\Testing\assertType;

/** @param int|float $floatOrInt */
function doFoo(int $i, float $f, $floatOrInt): void {
assertType('non-empty-list<float>', range(1, 9, .01));
assertType('array{1, 4, 7}', range(1, 9, 3));

assertType('non-empty-list<float>', range(1, 9999, .01));
assertType('non-empty-list<int<1, 9999>>', range(1, 9999, 3));

assertType('list<float|int>', range(1, 9999, $floatOrInt));
assertType('list<float|int>', range(1, 9999, $floatOrInt));

assertType('list<int>', range(1, 3, $i));
assertType('list<float|int>', range(1, 3, $f));

assertType('list<int>', range(1, 9999, $i));
assertType('list<float|int>', range(1, 9999, $f));
}

0 comments on commit 7a6a0fa

Please sign in to comment.