diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php index 14489c725..1fa1a82b3 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php @@ -92,10 +92,13 @@ class ArrayColumnReturnTypeProvider implements \Psalm\Plugin\Hook\FunctionReturn // calculate results if ($row_shape instanceof Type\Atomic\TKeyedArray) { if ((null !== $value_column_name) && isset($row_shape->properties[$value_column_name])) { - if ($input_array_not_empty) { + $result_element_type = $row_shape->properties[$value_column_name]; + // When the selected key is possibly_undefined, the resulting array can be empty + if ($input_array_not_empty && $result_element_type->possibly_undefined !== true) { $have_at_least_one_res = true; } - $result_element_type = $row_shape->properties[$value_column_name]; + //array_column skips undefined elements so resulting type is necesseraly defined + $result_element_type->possibly_undefined = false; } else { $result_element_type = Type::getMixed(); } diff --git a/tests/ArrayFunctionCallTest.php b/tests/ArrayFunctionCallTest.php index 92b174f3e..75d5b2b86 100644 --- a/tests/ArrayFunctionCallTest.php +++ b/tests/ArrayFunctionCallTest.php @@ -1151,6 +1151,8 @@ class ArrayFunctionCallTest extends TestCase function makeShapeArray(): array { return []; } /** @return array */ function makeUnionArray(): array { return []; } + /** @return array */ + function makeKeyedArray(): array { return []; } $a = array_column([[1], [2], [3]], 0); $b = array_column([["a" => 1], ["a" => 2], ["a" => 3]], "a"); $c = array_column([["k" => "a", "v" => 1], ["k" => "b", "v" => 2]], "v", "k"); @@ -1162,6 +1164,10 @@ class ArrayFunctionCallTest extends TestCase $i = array_column(makeShapeArray(), 0); $j = array_column(makeUnionArray(), 0); $k = array_column([[0 => "test"]], 0); + $l = array_column(makeKeyedArray(), "y"); + $m_prepare = makeKeyedArray(); + assert($m_prepare !== []); + $m = array_column($m_prepare, "y"); ', 'assertions' => [ '$a' => 'non-empty-list', @@ -1175,6 +1181,8 @@ class ArrayFunctionCallTest extends TestCase '$i' => 'list', '$j' => 'list', '$k' => 'non-empty-list', + '$l' => 'list', + '$m' => 'list', ], ], 'splatArrayIntersect' => [ @@ -1870,6 +1878,15 @@ class ArrayFunctionCallTest extends TestCase } }' ], + 'arrayColumnwithKeyedArrayWithoutRedundantUnion' => [ + ' $foos + */ + function foo(array $foos): void { + array_multisort($formLayoutFields, SORT_ASC, array_column($foos, "y")); + }' + ], ]; }