vimeo / psalm

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

Union array shapes get normalised to optional keys even when shapes are sealed #9495

Open ciaranmcnulty opened 1 year ago

ciaranmcnulty commented 1 year ago

Incorrect example removed

https://psalm.dev/r/5f8c0cdbd3

I may be misunderstanding things but in latest psalm my var $union is definitely either an array with BOOP key only or with BEEP key only.

However it gets normalised to array{BEEP?: ..., BOOP?: ...} with various odd side effects, including after an array_key_exists psalm seems to think both keys are definitely set

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

I found these snippets:

https://psalm.dev/r/5f8c0cdbd3 ```php
orklah commented 1 year ago

Psalm doesn't support having two array in a union and will always try to combine them into a single notation. When doing so, it will try to loose minimal meaning but in this case, it's forced to loose the "one of the offset is defined"

ciaranmcnulty commented 1 year ago

Can the reasons for not supporting it be addressed now there are sealed types?

and the result of array_key_exists seems just plain wrong

orklah commented 1 year ago

Sealed types don't really change the subject. The core issue is that there is only one slot for arrays in a Union. It's just a design limitation.

It can be addressed but it gonna be a big work.

And yeah, we shouldn't infer anything with array_key_exists here, you can create an issue for that