Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array_filter inference broken for arrow functions #2627

Closed
slepic opened this issue Jan 15, 2020 · 4 comments
Closed

array_filter inference broken for arrow functions #2627

slepic opened this issue Jan 15, 2020 · 4 comments
Labels

Comments

@slepic
Copy link

slepic commented Jan 15, 2020

I have this piece of code that filters an array<A|B> based on value type effectively restricting the return type of the array_filter call to array. Psalm is not able to infer this type reduction and so I have to introduce a variable and add comment informing psalm (and anyone else) that array is the actualy type returned by array_filter

interface X {}
class A {}
class B implements X {}
class P {
  private X $x;
  function __construct(X $x) {$this->x = $x;}
}

\array_map(
  fn($x) => new P($x),
  /** @var array<string, X> $dummy psalm would scream on the above line */
  $dummy = \array_filter(['a' => new A(), 'b' => new B()], fn($x) => $x instanceof X)
);

It would be nice if psalm could infer the type, but I have no idea if that's even possible...

PS: PHP 7.4 arrow functions are used in the snippet but that is not necesary to reproduce the problem I believe

@slepic
Copy link
Author

slepic commented Jan 15, 2020

Yes, if the comment is there, no issues. But if the dummy is removed I get this:

Psalm output (using commit 389af1b):

ERROR: PossiblyInvalidArgument - 11:19 - Argument 1 of P::__construct expects X, possibly different type A|B provided

@muglug muglug added the bug label Jan 15, 2020
@muglug muglug changed the title proposal: adjust type returned by array_filter infered from the filter callback array_filter inference broken for arrow functions Jan 15, 2020
@muglug
Copy link
Collaborator

muglug commented Jan 15, 2020

This is a simple bug – there's different behaviour for arrow functions: https://psalm.dev/r/2cb63c9069

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/2cb63c9069
<?php
  
class A {}
class B {}

$a = \array_filter(
  [new A(), new B()],
  function($x) {
    return $x instanceof B;
  }
);

$b = \array_filter(
  [new A(), new B()],
  fn($x) => $x instanceof B
);

echo $a;
echo $b;
Psalm output (using commit c07fd13):

ERROR: InvalidArgument - 18:6 - Argument 1 of echo expects string, array<int(0)|int(1), B> provided

ERROR: InvalidArgument - 19:6 - Argument 1 of echo expects string, array<int(0)|int(1), A|B> provided

@slepic
Copy link
Author

slepic commented Jan 15, 2020

@muglug Aha nice, when I dont use arrow function, it is ok without the dummy comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants