phpstan / phpstan

PHP Static Analysis Tool - discover bugs in your code without running it!
https://phpstan.org/
MIT License
13.04k stars 891 forks source link

array_column() on non-empty-list<non-empty-list<T>> returns list<T> instead of non-empty-list<T> #12161

Open sivlev opened 3 hours ago

sivlev commented 3 hours ago

Bug report

If I call the function array_column($array, $index) where $array is a <non-empty-list<non-empty-list<T>> and $index is a valid column index, I get a return.type error: Method should return non-empty-list<int> but returns list<int>.

Code snippet that reproduces the problem

https://phpstan.org/r/d7b62228-9193-4b64-81fc-1cb1f3a33eab

Expected output

Under those conditions, it is expected to get non-empty-list<T> provided the column index is valid.

Did PHPStan help you today? Did it make you happy in any way?

No response

herndlm commented 2 hours ago

Based on the type information in that function scope it is not clear that the offset 1 really exists though, right? E.g. for 0 it is because it's a non-empty-list, but any higher indices like that are uncertain. Does that make sense or am I missing something?

An alternative type would be a constant array. Or is the snippet maybe not fully representative of how you experienced that issue?

sivlev commented 1 hour ago

Sorry, I indeed oversimplified the code when making the snippet. In my original code the method has a parameter $index to indicate which column should be returned. The existence of $index is checked using isset(). Here is an updated snippet: https://phpstan.org/r/f23cd135-4580-4821-9cfe-9f23e88c0b87

Instead of isset() I tried to use an explicit condition whether the $index lies inside the range of the 0th row, but it, unfortunately, did not help either: https://phpstan.org/r/11ec29c7-d030-41c4-ba2d-5a2a7bd8462f