Skip to content

Commit e5543b3

Browse files
committed
Infer non-empty-ness after count($a) == count($b)
1 parent dd2717b commit e5543b3

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
22432243

22442244
$rightType = $scope->getType($rightExpr);
22452245

2246-
// (count($a) === $b)
2246+
// (count($a) === $expr)
22472247
if (
22482248
!$context->null()
22492249
&& $unwrappedLeftExpr instanceof FuncCall
@@ -2252,6 +2252,28 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
22522252
&& in_array(strtolower((string) $unwrappedLeftExpr->name), ['count', 'sizeof'], true)
22532253
&& $rightType->isInteger()->yes()
22542254
) {
2255+
// count($a) === count($b)
2256+
if (
2257+
$context->true()
2258+
&& $unwrappedRightExpr instanceof FuncCall
2259+
&& $unwrappedRightExpr->name instanceof Name
2260+
&& in_array($unwrappedRightExpr->name->toLowerString(), ['count', 'sizeof'], true)
2261+
&& count($unwrappedRightExpr->getArgs()) >= 1
2262+
) {
2263+
$leftArrayType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value);
2264+
$rightArrayType = $scope->getType($unwrappedRightExpr->getArgs()[0]->value);
2265+
2266+
if (
2267+
$leftArrayType->isArray()->yes() && $rightArrayType->isArray()->yes()
2268+
&& ($leftArrayType->isIterableAtLeastOnce()->yes() || $rightArrayType->isIterableAtLeastOnce()->yes())
2269+
) {
2270+
$arrayTypes = $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr);
2271+
return $arrayTypes->unionWith(
2272+
$this->create($unwrappedRightExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr),
2273+
);
2274+
}
2275+
}
2276+
22552277
if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) {
22562278
return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($expr);
22572279
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace ListCount2;
4+
5+
use function PHPStan\dumpType;
6+
use function PHPStan\debugScope;
7+
use function PHPStan\Testing\assertType;
8+
9+
class HelloWorld
10+
{
11+
/**
12+
* @param non-empty-list<int> $listA
13+
* @param list<int> $listB
14+
*/
15+
public function sayIdenticalLists($listA, array $listB): void
16+
{
17+
if (count($listA) === count($listB)) {
18+
assertType('non-empty-list<int>', $listB);
19+
}
20+
assertType('list<int>', $listB);
21+
}
22+
23+
/**
24+
* @param non-empty-list<int> $listA
25+
*/
26+
public function sayIdenticalList($listA, array $arrB): void
27+
{
28+
if (count($listA) === count($arrB)) {
29+
assertType('non-empty-array', $arrB);
30+
}
31+
assertType('array', $arrB);
32+
}
33+
34+
/**
35+
* @param non-empty-array<int> $arrA
36+
*/
37+
public function sayEqualArray($arrA, array $arrB): void
38+
{
39+
if (count($arrA) == count($arrB)) {
40+
assertType('non-empty-array', $arrB);
41+
}
42+
assertType('array', $arrB);
43+
}
44+
45+
/**
46+
* @param non-empty-array<int> $arrA
47+
* @param array<int> $arrB
48+
*/
49+
public function sayEqualIntArray($arrA, array $arrB): void
50+
{
51+
if (count($arrA) == count($arrB)) {
52+
assertType('non-empty-array<int>', $arrB);
53+
}
54+
assertType('array<int>', $arrB);
55+
}
56+
57+
/**
58+
* @param non-empty-array<int> $arrA
59+
* @param array<string> $arrB
60+
*/
61+
public function sayEqualStringArray($arrA, array $arrB): void
62+
{
63+
if (count($arrA) == count($arrB)) {
64+
assertType('non-empty-array<string>', $arrB);
65+
}
66+
assertType('array<string>', $arrB);
67+
}
68+
69+
/**
70+
* @param array<int> $arrA
71+
* @param array<string> $arrB
72+
*/
73+
public function sayUnknownArray($arrA, array $arrB): void
74+
{
75+
if (count($arrA) == count($arrB)) {
76+
assertType('array<int>', $arrA);
77+
assertType('array<string>', $arrB);
78+
}
79+
assertType('array<string>', $arrB);
80+
}
81+
}

0 commit comments

Comments
 (0)