phpstan
phpstan copied to clipboard
Array shape intersection incorrect when a value is a union of constants
Bug report
The examples below are derived from code where this issue surfaced for me and may be more complicated than necessary.
This works because the array shapes in question have an int at index 0: https://phpstan.org/r/b065b44f-5f92-4462-a5ca-b5d312280772
But when the value at index 0 is 0|1|2|3, int leaks into the resolved type of the adjacent value:
Code snippet that reproduces the problem
https://phpstan.org/r/edd0a6b2-b1f7-452a-88c2-8a9342e91781
Expected output
The intersection of array{0|1|2|3, int|Payload|string|null} and array{0|1|2|3, Payload} should be array{0|1|2|3, Payload}, not array{0|1|2|3, int|Payload}
Did PHPStan help you today? Did it make you happy in any way?
No response
I made some comments to make the problem more obvious: https://phpstan.org/r/78fb6f20-fa82-40cc-bcf5-fbd8c3dafad0 and I agree, this is a bug.
But I don't understand what's happening with TInput&T0. Because if I didn't overlook something, that's Payload&(0|1|2|3) and that really doesn't make sense.
Sorry, I'm on the wrong device to update the test, but T0=0|1|2|3 is incorrect; T0 is Payload in this case.
Alright, fixed example: https://phpstan.org/r/a983ae46-0e54-4e0b-ae24-d7b10c9a7936
@lkrms After the latest push in 2.0.x, PHPStan now reports different result with your code snippet:
@@ @@
-52: Dumped type: Pipeline<Payload, array, array{int, int|Payload|string|null}>
+52: Dumped type: Pipeline<Payload, array<mixed>, array{int, int|Payload|string|null}>
53: Dumped type: array{int, Payload}
-54: Dumped type: Pipeline<Payload, array, array{int, Payload}>
+54: Dumped type: Pipeline<Payload, array<mixed>, array{int, Payload}>
Full report
| Line | Error |
|---|---|
| 52 | `Dumped type: Pipeline<Payload, array |
| 53 | Dumped type: array{int, Payload} |
| 54 | Dumped type: Pipeline<Payload, array<mixed>, array{int, Payload}> |
@lkrms After the latest push in 2.0.x, PHPStan now reports different result with your code snippet:
@@ @@
-53: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload|string|null}>
+53: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload|string|null}>
54: Dumped type: array{0|1|2|3, Payload}
-55: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload}>
+55: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload}>
Full report
| Line | Error |
|---|---|
| 53 | `Dumped type: Pipeline<Payload, array |
| 54 | `Dumped type: array{0 |
| 55 | `Dumped type: Pipeline<Payload, array |
@ondrejmirtes After the latest push in 2.0.x, PHPStan now reports different result with your code snippet:
@@ @@
-53: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload|string|null}>
+53: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload|string|null}>
54: Dumped type: array{0|1|2|3, Payload}
-64: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload}>
+64: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload}>
Full report
| Line | Error |
|---|---|
| 53 | `Dumped type: Pipeline<Payload, array |
| 54 | `Dumped type: array{0 |
| 64 | `Dumped type: Pipeline<Payload, array |
@ondrejmirtes After the latest push in 2.0.x, PHPStan now reports different result with your code snippet:
@@ @@
-53: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload|string|null}>
+53: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload|string|null}>
54: Dumped type: array{0|1|2|3, Payload}
-64: Dumped type: Pipeline<Payload, array, array{0|1|2|3, int|Payload}>
+64: Dumped type: Pipeline<Payload, array<mixed>, array{0|1|2|3, int|Payload}>
Full report
| Line | Error |
|---|---|
| 53 | `Dumped type: Pipeline<Payload, array |
| 54 | `Dumped type: array{0 |
| 64 | `Dumped type: Pipeline<Payload, array |