vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 660 forks source link

`array_intersect_key` results in array<array-key, mixed> vs array<string, mixed> #10663

Open bkdotcom opened 8 months ago

bkdotcom commented 8 months ago

https://psalm.dev/r/16ba5c2e38

/**
 * @return array<string, mixed>
 */
function foo(array $values) {
    $default = array(
        'foo' => 'foo',
        'bar' => 'bar',
    );
    $return = \array_merge($default, $values);
    return \array_intersect_key($return, $default); // we know that keys are limited to 'foo'|'bar', 
                                                    // yet psalm infers array<array-key, mixed>
}

INFO: MixedReturnTypeCoercion - 4:12 - The declared return type 'array<string, mixed>' for foo is more specific than the inferred return type 'array<array-key, 'bar'|'foo'|mixed>'

It knows the values are 'bar'|'foo'|mixed, but doesn't know the keys are 'foo'|'bar'?

which leads to .. ERROR: MixedArgumentTypeCoercion when passing the results to another method

do I need to add some annotation?

psalm-github-bot[bot] commented 8 months ago

I found these snippets:

https://psalm.dev/r/16ba5c2e38 ```php */ function foo(array $values) { $default = array( 'foo' => 'foo', 'bar' => 'bar', ); $return = \array_merge($default, $values); return \array_intersect_key($return, $default); } ``` ``` Psalm output (using commit 4b2c698): INFO: MixedReturnTypeCoercion - 12:12 - The type 'array' is more general than the declared return type 'array' for foo INFO: MixedReturnTypeCoercion - 4:12 - The declared return type 'array' for foo is more specific than the inferred return type 'array' ```
weirdan commented 8 months ago

This would require a specific return type provider. Currently we only have a generic stub for array_intersect_key(): https://github.com/vimeo/psalm/blob/62b525993d6091c8c2b95bfdc0b70a4e077e6f1e/stubs/CoreGenericFunctions.phpstub#L30-L42