vimeo / psalm

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

Union type of object treats as intersection #9640

Open the-toster opened 1 year ago

the-toster commented 1 year ago

So, isset checks give RedundantCondition https://psalm.dev/r/927830ba95

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/927830ba95 ```php a ?? ''; } ``` ``` Psalm output (using commit 71bb951): ERROR: RedundantCondition - 21:10 - Type string for $obj->a is always isset ERROR: TypeDoesNotContainType - 21:21 - Cannot resolve types for $obj->a with type string and !isset assertion ```
orklah commented 1 year ago

That's not quite what happens: https://psalm.dev/r/009b09cc05

In fact, when you try to access the property, psalm infers mixed|string. So it correctly gets string from A but it takes mixed from B.

It could be correct if B had something like a __get method but Psalm considers object without magic method to have sealed properties (the default behaviour in recent php versions) so it should emit something like PossiblyUndefinedPropertyFetch here.

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/009b09cc05 ```php a; /** @psalm-trace $a */; echo $obj->a ?? ''; } ``` ``` Psalm output (using commit 71bb951): ERROR: UndefinedPropertyFetch - 21:10 - Instance property B::$a is not defined INFO: MixedAssignment - 21:5 - Unable to determine the type that $a is being assigned to INFO: Trace - 22:27 - $a: mixed|string INFO: MixedArgument - 24:10 - Argument 1 of echo cannot be mixed|string, expecting string INFO: UnusedVariable - 21:5 - $a is never referenced or the value is not used ```