Skip to content

Nested array return value false positive when using template T of array #9828

@ArtemGoutsoul

Description

@ArtemGoutsoul

Bug report

Consider the following example. The function is filtering a 2d array based on a value in the inner array. The input array can contain multiple keys, but we only care about an int element with the key 'value'. The returned array should contain the elements with the same keys, but possibly fewer.

/**
 * @template T of array{value: int, ...}
 * @param array<int, T> $array
 * @return array<int, T>
 */
function filter(array $array, int $min_value): array
{
	foreach ($array as $key => $row) {
		if ($row['value'] < $min_value) unset($array[$key]);
	}
	return array_values($array);
}

I get an error:

Function filter() should return array<int, T of array{value: int}> but returns array<int, array{value: int}>.
Type array{value: int} is not always the same as T. It breaks the contract for some argument types, typically subtypes.

The returned array structure is clearly the same and should match the template, but phpstan disagrees :) Iäm not sure how to modify the code or annotations to make it work.

Playground has one more similar example (tried to rebuild the array).

Code snippet that reproduces the problem

https://phpstan.org/r/d9abcd5f-d336-406d-9e25-b2750bcc789e

Expected output

No error

Did PHPStan help you today? Did it make you happy in any way?

PHPStan always makes me happy, @ondrejmirtes and the team are awesome! :)

I don't know how other dynamic language ecosystems survive without tools like phpstan and psalm! (python I'm looking at you! mypy just doesn't cut it)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions