psalm icon indicating copy to clipboard operation
psalm copied to clipboard

False positive for ArrayAccess and Traversable (UndefinedInterfaceMethod PossibleRawObjectIteration )

Open jordisala1991 opened this issue 2 years ago • 4 comments

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

jordisala1991 avatar May 06 '22 06:05 jordisala1991

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

psalm-github-bot[bot] avatar May 06 '22 06:05 psalm-github-bot[bot]

Some of these conditionals end up being a bit difficult, it looks like it works if you separate it out like this.

AndrolGenhald avatar May 06 '22 19:05 AndrolGenhald

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

psalm-github-bot[bot] avatar May 06 '22 19:05 psalm-github-bot[bot]

Note: the original psalm.dev link now reproduce the issue

orklah avatar Jul 29 '22 17:07 orklah