vimeo / psalm

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

Intersection with an imported type #5148

Open egst opened 3 years ago

egst commented 3 years ago

https://psalm.dev/r/ec2d56f41d

When I try to make an intersection type with an imported type, I get the following error:

Intersection types must be all objects or all object-like arrays, Psalm\Type\Atomic\TKeyedArray provided

Isn't TKeyedArray an object-like array? This seems like a bug to me, but maybe I'm not getting something right.

psalm-github-bot[bot] commented 3 years ago

I found these snippets:

https://psalm.dev/r/ec2d56f41d ```php
egst commented 3 years ago

A possible workaround would be to introduce a dummy helper class with the second type definition and to import both types and only then perform the intersection on them.

https://psalm.dev/r/8ea579671b

psalm-github-bot[bot] commented 3 years ago

I found these snippets:

https://psalm.dev/r/8ea579671b ```php
douggr commented 3 years ago

A possible workaround would be to introduce a dummy helper class with the second type definition and to import both types and only then perform the intersection on them.

https://psalm.dev/r/8ea579671b

yet, it doesn't work if you try to use Q within types or returns; or am I missing something here?

https://psalm.dev/r/1eaa0c447f

psalm-github-bot[bot] commented 3 years ago

I found these snippets:

https://psalm.dev/r/8ea579671b ```php
https://psalm.dev/r/1eaa0c447f ```php 10]; } /** @psalm-type Y = array{y: int} */ class _ { /** @var Y */ protected $foo = ['y' => 10]; } /** * @psalm-import-type X from A * @psalm-import-type Y from _ * @psalm-type Q = X&Y */ class B { /** @var X */ protected $x = ['x' => 10]; /** @var Y */ protected $y = ['y' => 10]; /** @var Q */ protected $q = ['x' => 1, 'y' => 2]; /** @psalm-return Q */ function getQ(): array { return $this->q; } /** @psalm-param Q $input */ function setQ(array $input): void { $this->q = $input; } } ``` ``` Psalm output (using commit 3046468): ERROR: InvalidDocblock - 31:5 - Invalid type alias X provided in docblock for B::getQ ERROR: InvalidDocblock - 36:22 - Invalid type alias X provided in docblock for B::setQ INFO: MixedPropertyTypeCoercion - 39:20 - $this->q expects 'array{x: int}', parent type `array` provided ERROR: InvalidDocblock - 28:5 - Q is not a valid type (from /var/www/vhosts/psalm.dev/httpdocs/src/somefile.php:27) ```
orklah commented 2 years ago

Error was clarified, intersections with array shapes are not supported

egst commented 2 years ago

@orklah, but intersections with array shapes are supported, aren't they? It's just the intersections with imported array shape types that cause problems. And why would you actually not support intersections with imported types? It just feels like a natural thing. It's like if you could include a file in PHP bud you couldn't call included functions inside of other functions and the PHP developer's solution would be to just clarify the error that it is not supported.

orklah commented 2 years ago

You're right, I was confused, the basic version works, but here, the second example doesn't either: https://psalm.dev/r/9ddbcacb2f

The error is still kinda misleading. I'll flag this as enhancement

psalm-github-bot[bot] commented 2 years ago

I found these snippets:

https://psalm.dev/r/9ddbcacb2f ```php
VincentLanglet commented 2 years ago

I just encountered this bug in a situation like https://psalm.dev/r/324fd96838

This shouldn't be too hard to fix, since it is working with the typeAlias last https://psalm.dev/r/89e0dffd1b

psalm-github-bot[bot] commented 2 years ago

I found these snippets:

https://psalm.dev/r/324fd96838 ```php
https://psalm.dev/r/89e0dffd1b ```php