Skip to content

Commit

Permalink
Array map on multiple elements is a list
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentLanglet committed Dec 9, 2024
1 parent 09eab21 commit c641108
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 9 deletions.
10 changes: 6 additions & 4 deletions src/Type/Php/ArrayMapFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
);
}
} else {
$mappedArrayType = TypeCombinator::intersect(new ArrayType(
new IntegerType(),
$valueType,
), ...TypeUtils::getAccessoryTypes($arrayType));
$mappedArrayType = AccessoryArrayListType::intersectWith(
TypeCombinator::intersect(new ArrayType(
new IntegerType(),
$valueType,
), ...TypeUtils::getAccessoryTypes($arrayType)),
);
}

if ($arrayType->isIterableAtLeastOnce()->yes()) {
Expand Down
10 changes: 5 additions & 5 deletions tests/PHPStan/Analyser/nsrt/array_map_multiple.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function doFoo(int $i, string $s): void

return rand(0, 1) ? $a : $b;
}, ['foo' => $i], ['bar' => $s]);
assertType('non-empty-array<int, int|string>', $result);
assertType('non-empty-list<int|string>', $result);
}

/**
Expand All @@ -26,12 +26,12 @@ public function arrayMapNull(array $array, array $other): void
{
assertType('array{}', array_map(null, []));
assertType('array{foo: true}', array_map(null, ['foo' => true]));
assertType('non-empty-array<int, array{1|2|3, 4|5|6}>', array_map(null, [1, 2, 3], [4, 5, 6]));
assertType('non-empty-list<array{1|2|3, 4|5|6}>', array_map(null, [1, 2, 3], [4, 5, 6]));

assertType('non-empty-array<string, int>', array_map(null, $array));
assertType('non-empty-array<int, array{int, int}>', array_map(null, $array, $array));
assertType('non-empty-array<int, array{int, int, int}>', array_map(null, $array, $array, $array));
assertType('non-empty-array<int, array{int|null, bool|null}>', array_map(null, $array, $other));
assertType('non-empty-list<array{int, int}>', array_map(null, $array, $array));
assertType('non-empty-list<array{int, int, int}>', array_map(null, $array, $array, $array));
assertType('non-empty-list<array{int|null, bool|null}>', array_map(null, $array, $other));

assertType('array{1}|array{true}', array_map(null, rand() ? [1] : [true]));
assertType('array{1}|array{true, false}', array_map(null, rand() ? [1] : [true, false]));
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1064,4 +1064,9 @@ public function testBug11857(): void
$this->analyse([__DIR__ . '/data/bug-11857-builder.php'], []);
}

public function testBug12223(): void
{
$this->analyse([__DIR__ . '/data/bug-12223.php'], []);
}

}
15 changes: 15 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-12223.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Bug12223;

class HelloWorld
{
/**
* @return list<string>
*/
public function sayHello(): array
{
$a = [1 => 'foo', 3 => 'bar', 5 => 'baz'];
return array_map(static fn(string $s, int $i): string => $s . $i, $a, array_keys($a));
}
}

0 comments on commit c641108

Please sign in to comment.