Skip to content

Commit ad7dce2

Browse files
authored
min() and max() may return false if array size could be zero
1 parent 4081f12 commit ad7dce2

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/Type/Php/MinMaxFunctionReturnTypeExtension.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Reflection\FunctionReflection;
88
use PHPStan\Reflection\ParametersAcceptorSelector;
99
use PHPStan\Type\Constant\ConstantArrayType;
10+
use PHPStan\Type\Constant\ConstantBooleanType;
1011
use PHPStan\Type\ConstantScalarType;
1112
use PHPStan\Type\ConstantType;
1213
use PHPStan\Type\ErrorType;
@@ -37,8 +38,15 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
3738
if (count($functionCall->args) === 1) {
3839
$argType = $scope->getType($functionCall->args[0]->value);
3940
if ($argType->isArray()->yes()) {
41+
$isIterable = $argType->isIterableAtLeastOnce();
42+
if ($isIterable->no()) {
43+
return new ConstantBooleanType(false);
44+
}
4045
$iterableValueType = $argType->getIterableValueType();
4146
$argumentTypes = [];
47+
if (!$isIterable->yes()) {
48+
$argumentTypes[] = new ConstantBooleanType(false);
49+
}
4250
if ($iterableValueType instanceof UnionType) {
4351
foreach ($iterableValueType->getTypes() as $innerType) {
4452
$argumentTypes[] = $innerType;

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10009,6 +10009,11 @@ public function dataNativeMixedType(): array
1000910009
return $this->gatherAssertTypes(__DIR__ . '/../Reflection/data/mixedType.php');
1001010010
}
1001110011

10012+
public function dataMinMaxReturnTypeWithArrays(): array
10013+
{
10014+
return $this->gatherAssertTypes(__DIR__ . '/data/minmax-arrays.php');
10015+
}
10016+
1001210017
/**
1001310018
* @dataProvider dataBug2574
1001410019
* @dataProvider dataBug2577
@@ -10070,6 +10075,7 @@ public function dataNativeMixedType(): array
1007010075
* @dataProvider dataBitwiseNot
1007110076
* @dataProvider dataGraphicsDrawReturnTypes
1007210077
* @dataProvider dataNativeUnionTypes
10078+
* @dataProvider dataMinMaxReturnTypeWithArrays
1007310079
* @param string $assertType
1007410080
* @param string $file
1007510081
* @param mixed ...$args
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace MinMaxArrays;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
function dummy(): void
8+
{
9+
assertType('1', min([1]));
10+
assertType('false', min([]));
11+
assertType('1', max([1]));
12+
assertType('false', max([]));
13+
}
14+
15+
/**
16+
* @param int[] $ints
17+
*/
18+
function dummy2(array $ints): void
19+
{
20+
if (count($ints) !== 0) {
21+
assertType('int', min($ints));
22+
assertType('int', max($ints));
23+
} else {
24+
assertType('false', min($ints));
25+
assertType('false', max($ints));
26+
}
27+
}
28+
29+
/**
30+
* @param int[] $ints
31+
*/
32+
function dummy3(array $ints): void
33+
{
34+
assertType('int|false', min($ints));
35+
assertType('int|false', max($ints));
36+
}

0 commit comments

Comments
 (0)