Skip to content

Commit 056318f

Browse files
authored
Merge branch refs/heads/2.1.x into 2.2.x
2 parents 10cdfe3 + 677d53f commit 056318f

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,23 @@ private function specifyTypesForCountFuncCall(
12791279
return null;
12801280
}
12811281

1282+
if ($context->falsey() && $isConstantArray->yes()) {
1283+
$remainingSize = TypeCombinator::remove($type->getArraySize(), $sizeType);
1284+
if (!$remainingSize instanceof NeverType) {
1285+
$result = $this->specifyTypesForCountFuncCall(
1286+
$countFuncCall,
1287+
$type,
1288+
$remainingSize,
1289+
$context->negate(),
1290+
$scope,
1291+
$rootExpr,
1292+
);
1293+
if ($result !== null) {
1294+
return $result;
1295+
}
1296+
}
1297+
}
1298+
12821299
$resultTypes = [];
12831300
foreach ($type->getArrays() as $arrayType) {
12841301
$isSizeSuperTypeOfArraySize = $sizeType->isSuperTypeOf($arrayType->getArraySize());
@@ -1372,7 +1389,14 @@ private function specifyTypesForCountFuncCall(
13721389
$builder->setOffsetValueType($offsetType, $valueType, $optional);
13731390
}
13741391

1375-
$resultTypes[] = $builder->getArray();
1392+
$builtArray = $builder->getArray();
1393+
if ($isList->yes() && !$builder->isList()) {
1394+
$constantArrays = $builtArray->getConstantArrays();
1395+
if (count($constantArrays) === 1) {
1396+
$builtArray = $constantArrays[0]->makeList();
1397+
}
1398+
}
1399+
$resultTypes[] = $builtArray;
13761400
continue;
13771401
}
13781402

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14297;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function (): void {
8+
$a = [rand(0, 1) ? 'a' : null];
9+
if (rand(0, 1)) {
10+
$a[] = rand(0, 1) ? 'b' : null;
11+
}
12+
13+
$a = array_values(array_filter($a));
14+
if (count($a) === 0) {
15+
return;
16+
}
17+
18+
assertType("non-empty-list{0?: 'a'|'b', 1?: 'b'}", $a);
19+
assertType("int<1, 2>", count($a));
20+
21+
if (count($a) === 2) {
22+
assertType("array{'a'|'b', 'b'}", $a);
23+
} else {
24+
assertType("array{'a'|'b'}", $a);
25+
}
26+
};

tests/PHPStan/Analyser/nsrt/list-count.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,13 @@ protected function testOptionalKeys($row): void
233233
if (count($row) === 1) {
234234
assertType('array{mixed}', $row);
235235
} else {
236-
assertType('array{0: mixed, 1?: string|null}', $row);
236+
assertType('array{mixed, string|null}', $row);
237237
}
238238

239239
if (count($row) === 2) {
240240
assertType('array{mixed, string|null}', $row);
241241
} else {
242-
assertType('array{0: mixed, 1?: string|null}', $row);
242+
assertType('array{mixed}', $row);
243243
}
244244

245245
if (count($row) === 3) {
@@ -263,13 +263,13 @@ protected function testOptionalKeysInUnion($row): void
263263
if (count($row) === 1) {
264264
assertType('array{mixed}', $row);
265265
} else {
266-
assertType('array{0: mixed, 1?: string|null}', $row);
266+
assertType('array{mixed, string|null}', $row);
267267
}
268268

269269
if (count($row) === 2) {
270270
assertType('array{mixed, string|null}', $row);
271271
} else {
272-
assertType('array{0: mixed, 1?: string|null}', $row);
272+
assertType('array{mixed}', $row);
273273
}
274274

275275
if (count($row) === 3) {
@@ -293,7 +293,7 @@ protected function testOptionalKeysInListsOfTaggedUnion($row): void
293293
if (count($row) === 1) {
294294
assertType('array{0: int, 1?: string|null}|array{string}', $row);
295295
} else {
296-
assertType('array{0: int, 1?: string|null}', $row);
296+
assertType('array{int, string|null}', $row);
297297
}
298298

299299
if (count($row) === 2) {

0 commit comments

Comments
 (0)