Skip to content

Commit 2f6d369

Browse files
committed
Improve count on list with greater/smaller-than
1 parent 75f243d commit 2f6d369

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
3939
use PHPStan\Type\Accessory\AccessoryNonFalsyStringType;
4040
use PHPStan\Type\Accessory\HasOffsetType;
41+
use PHPStan\Type\Accessory\HasOffsetValueType;
4142
use PHPStan\Type\Accessory\HasPropertyType;
4243
use PHPStan\Type\Accessory\NonEmptyArrayType;
4344
use PHPStan\Type\ArrayType;
@@ -1197,7 +1198,23 @@ private function specifyTypesForCountFuncCall(
11971198
$builderData[] = [$offsetType, $arrayType->getOffsetValueType($offsetType), !$hasOffset->yes()];
11981199
}
11991200
} else {
1200-
$resultTypes[] = TypeCombinator::intersect($arrayType, new NonEmptyArrayType());
1201+
$intersection = [];
1202+
$intersection[] = $arrayType;
1203+
$intersection[] = new NonEmptyArrayType();
1204+
1205+
$zero = new ConstantIntegerType(0);
1206+
foreach ($builderData as [$offsetType, $valueType, $optional]) {
1207+
if (
1208+
$optional
1209+
// list already is non-empty
1210+
|| $zero->isSuperTypeOf($offsetType)->yes()
1211+
) {
1212+
continue;
1213+
}
1214+
$intersection[] = new HasOffsetValueType($offsetType, $valueType);
1215+
}
1216+
1217+
$resultTypes[] = TypeCombinator::intersect(...$intersection);
12011218
continue;
12021219
}
12031220

tests/PHPStan/Analyser/nsrt/bug-11642.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function doFoo() {
3434
if (count($entries) !== count($payload->ids)) {
3535
exit();
3636
}
37+
assertType('int<1, max>', count($entries));
3738

3839
assertType('non-empty-list<stdClass>', $entries);
3940
if (count($entries) > 3) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types = 1);
2+
3+
use function PHPStan\dumpType;
4+
use function PHPStan\Testing\assertType;
5+
6+
class HelloWorld
7+
{
8+
/** @param list<int> $list */
9+
public function sayHello($list): void
10+
{
11+
if (count($list) === 0) {
12+
return;
13+
}
14+
15+
if (count($list) > 2) {
16+
assertType('non-empty-list<int>&hasOffsetValue(0, int)&hasOffsetValue(1, int)&hasOffsetValue(2, int)', $list);
17+
} else {
18+
assertType('non-empty-list<int>', $list);
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)