psalm
psalm copied to clipboard
False positive for ArrayAccess and Traversable (UndefinedInterfaceMethod PossibleRawObjectIteration )
We are trying to detect if a variable can be passed through a foreach and can be acces directly at a position (to do an unset), here is the code:
https://github.com/sonata-project/form-extensions/blob/2.x/src/EventListener/ResizeFormListener.php#L167-L178
When moving to Psalm level 2 we get this error:
ERROR: PossibleRawObjectIteration - src/EventListener/ResizeFormListener.php:178:18 - Possibly undesired iteration over regular object ArrayAccess (see https://psalm.dev/208)
foreach ($data as $name => $child) {
Related PR: https://github.com/sonata-project/form-extensions/pull/319 We tried to reproduce it: https://psalm.dev/r/c95d52a172
I found these snippets:
https://psalm.dev/r/c95d52a172
<?php
function foo(mixed $data): void {
if (
!\is_array($data)
&& (!$data instanceof \Traversable || !$data instanceof \ArrayAccess)
) {
throw new \Exception('array or \Traversable&\ArrayAccess');
}
/** @psalm-trace $data */
foreach ($data as $name => $value) {
unset($data[$name]);
}
}
Psalm output (using commit f960d71):
INFO: MixedAssignment - 13:32 - Unable to determine the type that $value is being assigned to
ERROR: UndefinedInterfaceMethod - 14:15 - Method Traversable::offsetGet does not exist
INFO: Trace - 13:5 - $data: Traversable|array<array-key, mixed>
INFO: UnusedForeachValue - 13:32 - $value is never referenced or the value is not used
Some of these conditionals end up being a bit difficult, it looks like it works if you separate it out like this.
I found these snippets:
https://psalm.dev/r/73779a3244
<?php
function foo(mixed $data): void {
if (\is_array($data)) {
} elseif ($data instanceof \Traversable && $data instanceof \ArrayAccess) {
} else {
throw new \Exception('array or \Traversable&\ArrayAccess');
}
/** @psalm-trace $data */
foreach ($data as $name => $value) {
unset($data[$name]);
}
}
Psalm output (using commit f960d71):
INFO: MixedAssignment - 11:32 - Unable to determine the type that $value is being assigned to
INFO: Trace - 11:5 - $data: Traversable&ArrayAccess|array<array-key, mixed>
INFO: UnusedForeachValue - 11:32 - $value is never referenced or the value is not used
Note: the original psalm.dev link now reproduce the issue