Skip to content

Commit 713770b

Browse files
committed
Infer non-empty-array after array_key_first/last()
1 parent 40c2377 commit 713770b

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,21 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
23462346
}
23472347
}
23482348

2349+
// array_key_first($a) !== null
2350+
// array_key_last($a) !== null
2351+
if (
2352+
$unwrappedLeftExpr instanceof FuncCall
2353+
&& $unwrappedLeftExpr->name instanceof Name
2354+
&& in_array($unwrappedLeftExpr->name->toLowerString(), ['array_key_first', 'array_key_last'], true)
2355+
&& isset($unwrappedLeftExpr->getArgs()[0])
2356+
&& $rightType->isNull()->yes()
2357+
) {
2358+
$argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value);
2359+
if ($argType->isArray()->yes()) {
2360+
return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr);
2361+
}
2362+
}
2363+
23492364
// preg_match($a) === $b
23502365
if (
23512366
$context->true()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
namespace Bug13546;
3+
4+
use function PHPStan\Testing\assertType;
5+
6+
/** @param array<int> $array */
7+
function first(array $array): void
8+
{
9+
if (array_key_first($array) !== null) {
10+
assertType('non-empty-array<int>', $array);
11+
} else {
12+
assertType('array{}', $array);
13+
}
14+
assertType('array<int>', $array);
15+
}
16+
17+
/** @param array<int> $array */
18+
function firstReversed(array $array): void
19+
{
20+
if (null !== array_key_first($array)) {
21+
assertType('non-empty-array<int>', $array);
22+
} else {
23+
assertType('array{}', $array);
24+
}
25+
assertType('array<int>', $array);
26+
}
27+
28+
/** @param array<int> $array */
29+
function last(array $array): void
30+
{
31+
if (array_key_last($array) !== null) {
32+
assertType('non-empty-array<int>', $array);
33+
} else {
34+
assertType('array{}', $array);
35+
}
36+
assertType('array<int>', $array);
37+
}

0 commit comments

Comments
 (0)