Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d0e7aca

Browse files
schlndhondrejmirtes
authored andcommitted
don't add null for array_map(null, $a, $a)
1 parent 8038a29 commit d0e7aca

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

‎src/Type/Php/ArrayMapFunctionReturnTypeExtension.php‎

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use PHPStan\Type\TypeCombinator;
2020
use PHPStan\Type\TypeUtils;
2121
use function array_map;
22+
use function array_reduce;
2223
use function array_slice;
2324
use function count;
2425

@@ -55,19 +56,18 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
5556
)->getReturnType();
5657
} elseif ($callableIsNull) {
5758
$arrayBuilder = ConstantArrayTypeBuilder::createEmpty();
58-
$argIterableValueTypes = [];
59-
$addNull = false;
59+
$argTypes = [];
60+
$areAllSameSize = true;
6061
$expectedSize = null;
6162
foreach (array_slice($functionCall->getArgs(), 1) as $index => $arg) {
62-
$argType = $scope->getType($arg->value);
63-
$argIterableValueTypes[$index] = $argType->getIterableValueType();
64-
if ($addNull) {
63+
$argTypes[$index] = $argType = $scope->getType($arg->value);
64+
if (!$areAllSameSize || $numArgs === 2) {
6565
continue;
6666
}
6767

6868
$arraySizes = $argType->getArraySize()->getConstantScalarValues();
6969
if ($arraySizes === []) {
70-
$addNull = true;
70+
$areAllSameSize = false;
7171
continue;
7272
}
7373

@@ -77,12 +77,30 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
7777
continue;
7878
}
7979

80-
$addNull = true;
81-
break;
80+
$areAllSameSize = false;
81+
continue2;
8282
}
8383
}
8484

85-
foreach ($argIterableValueTypes as $index => $offsetValueType) {
85+
if (!$areAllSameSize) {
86+
$firstArr = $functionCall->getArgs()[1]->value;
87+
$identities = [];
88+
foreach (array_slice($functionCall->getArgs(), 2) as $arg) {
89+
$identities[] = new Node\Expr\BinaryOp\Identical($firstArr, $arg->value);
90+
}
91+
92+
$and = array_reduce(
93+
$identities,
94+
static fn (Node\Expr $a, Node\Expr $b) => new Node\Expr\BinaryOp\BooleanAnd($a, $b),
95+
new Node\Expr\ConstFetch(new Node\Name('true')),
96+
);
97+
$areAllSameSize = $scope->getType($and)->isTrue()->yes();
98+
}
99+
100+
$addNull = !$areAllSameSize;
101+
102+
foreach ($argTypes as $index => $argType) {
103+
$offsetValueType = $argType->getIterableValueType();
86104
if ($addNull) {
87105
$offsetValueType = TypeCombinator::addNull($offsetValueType);
88106
}

‎tests/PHPStan/Analyser/nsrt/array_map_multiple.php‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ public function arrayMapNull(array $array, array $other): void
2929
assertType('non-empty-array<int, array{1|2|3, 4|5|6}>', array_map(null, [1, 2, 3], [4, 5, 6]));
3030

3131
assertType('non-empty-array<string, int>', array_map(null, $array));
32-
assertType('non-empty-array<int, array{int|null, int|null}>', array_map(null, $array, $array));
32+
assertType('non-empty-array<int, array{int, int}>', array_map(null, $array, $array));
33+
assertType('non-empty-array<int, array{int, int, int}>', array_map(null, $array, $array, $array));
3334
assertType('non-empty-array<int, array{int|null, bool|null}>', array_map(null, $array, $other));
35+
36+
assertType('array{1}|array{true}', array_map(null, rand() ? [1] : [true]));
37+
assertType('array{1}|array{true, false}', array_map(null, rand() ? [1] : [true, false]));
3438
}
3539

3640
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /