Skip to content

Commit

Permalink
min() and max() may return false if array size could be zero
Browse files Browse the repository at this point in the history
  • Loading branch information
dktapps committed Aug 16, 2020
1 parent 4081f12 commit ad7dce2
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/Type/Php/MinMaxFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\ConstantType;
use PHPStan\Type\ErrorType;
Expand Down Expand Up @@ -37,8 +38,15 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
if (count($functionCall->args) === 1) {
$argType = $scope->getType($functionCall->args[0]->value);
if ($argType->isArray()->yes()) {
$isIterable = $argType->isIterableAtLeastOnce();
if ($isIterable->no()) {
return new ConstantBooleanType(false);
}
$iterableValueType = $argType->getIterableValueType();
$argumentTypes = [];
if (!$isIterable->yes()) {
$argumentTypes[] = new ConstantBooleanType(false);
}
if ($iterableValueType instanceof UnionType) {
foreach ($iterableValueType->getTypes() as $innerType) {
$argumentTypes[] = $innerType;
Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10009,6 +10009,11 @@ public function dataNativeMixedType(): array
return $this->gatherAssertTypes(__DIR__ . '/../Reflection/data/mixedType.php');
}

public function dataMinMaxReturnTypeWithArrays(): array
{
return $this->gatherAssertTypes(__DIR__ . '/data/minmax-arrays.php');
}

/**
* @dataProvider dataBug2574
* @dataProvider dataBug2577
Expand Down Expand Up @@ -10070,6 +10075,7 @@ public function dataNativeMixedType(): array
* @dataProvider dataBitwiseNot
* @dataProvider dataGraphicsDrawReturnTypes
* @dataProvider dataNativeUnionTypes
* @dataProvider dataMinMaxReturnTypeWithArrays
* @param string $assertType
* @param string $file
* @param mixed ...$args
Expand Down
36 changes: 36 additions & 0 deletions tests/PHPStan/Analyser/data/minmax-arrays.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace MinMaxArrays;

use function PHPStan\Analyser\assertType;

function dummy(): void
{
assertType('1', min([1]));
assertType('false', min([]));
assertType('1', max([1]));
assertType('false', max([]));
}

/**
* @param int[] $ints
*/
function dummy2(array $ints): void
{
if (count($ints) !== 0) {
assertType('int', min($ints));
assertType('int', max($ints));
} else {
assertType('false', min($ints));
assertType('false', max($ints));
}
}

/**
* @param int[] $ints
*/
function dummy3(array $ints): void
{
assertType('int|false', min($ints));
assertType('int|false', max($ints));
}

0 comments on commit ad7dce2

Please sign in to comment.