From 8092d6b7afa80fddfecffdcc3a857a86e7e4e89c Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Thu, 5 Dec 2024 15:51:50 +0100 Subject: [PATCH] Consider int range offset in truthy context --- src/Analyser/TypeSpecifier.php | 21 ++++++--------------- tests/PHPStan/Analyser/nsrt/bug-4700.php | 6 +++--- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index aa5efbd468..f15784b081 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -277,7 +277,7 @@ public function specifyTypesInCondition( $sizeType = IntegerRangeType::createAllGreaterThan($leftType->getValue()); } } elseif ($leftType instanceof IntegerRangeType) { - $sizeType = $leftType; + $sizeType = $leftType->shift($offset); } $specifiedTypes = $this->specifyTypesForCountFuncCall($expr->right, $argType, $sizeType, $context, $scope, $expr); @@ -984,23 +984,14 @@ private function specifyTypesForCountFuncCall(FuncCall $countFuncCall, Type $typ $arraySize = $type->getArraySize(); $isSize = $sizeType->isSuperTypeOf($arraySize); - if ($context->truthy()) { - if ($isSize->no()) { - return new NeverType(); - } - - $constArray = $this->turnListIntoConstantArray($type, $sizeType); - if ($constArray !== null) { - $type = $constArray; - } + if ($context->truthy() && $isSize->no()) { + return new NeverType(); } - if ($context->falsey()) { - if (!$isSize->yes()) { - return new NeverType(); - } + if ($context->falsey() && !$isSize->yes()) { + return new NeverType(); } - return $type; + return $this->turnListIntoConstantArray($type, $sizeType) ?? $type; }); return $this->create($countFuncCall->getArgs()[0]->value, $resultType, $context, $scope)->setRootExpr($rootExpr); diff --git a/tests/PHPStan/Analyser/nsrt/bug-4700.php b/tests/PHPStan/Analyser/nsrt/bug-4700.php index 202aca765c..9d386b0c50 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4700.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4700.php @@ -41,9 +41,9 @@ function(array $array, int $count): void { if (isset($array['e'])) $a[] = $array['e']; if (count($a) > $count) { assertType('int<2, 5>', count($a)); - assertType('array{0: mixed~null, 1?: mixed~null, 2?: mixed~null, 3?: mixed~null, 4?: mixed~null}', $a); + assertType('list{0: mixed~null, 1: mixed~null, 2?: mixed~null, 3?: mixed~null, 4?: mixed~null}', $a); } else { - assertType('0', count($a)); - assertType('array{}', $a); + assertType('int<0, 5>', count($a)); // Could be int<0, 1> + assertType('array{}|array{0: mixed~null, 1?: mixed~null, 2?: mixed~null, 3?: mixed~null, 4?: mixed~null}', $a); // Could be array{}|array{0: mixed~null} } };