diff --git a/src/Type/Php/RangeFunctionReturnTypeExtension.php b/src/Type/Php/RangeFunctionReturnTypeExtension.php index ed43f64f20..aceaebf670 100644 --- a/src/Type/Php/RangeFunctionReturnTypeExtension.php +++ b/src/Type/Php/RangeFunctionReturnTypeExtension.php @@ -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(), @@ -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(), diff --git a/tests/PHPStan/Analyser/nsrt/bug-11692.php b/tests/PHPStan/Analyser/nsrt/bug-11692.php new file mode 100644 index 0000000000..c1edbba1fd --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11692.php @@ -0,0 +1,24 @@ +', range(1, 9, .01)); + assertType('array{1, 4, 7}', range(1, 9, 3)); + + assertType('non-empty-list', range(1, 9999, .01)); + assertType('non-empty-list>', range(1, 9999, 3)); + + assertType('list', range(1, 9999, $floatOrInt)); + assertType('list', range(1, 9999, $floatOrInt)); + + assertType('list', range(1, 3, $i)); + assertType('list', range(1, 3, $f)); + + assertType('list', range(1, 9999, $i)); + assertType('list', range(1, 9999, $f)); +} +