psalm icon indicating copy to clipboard operation
psalm copied to clipboard

Regression: incorrectly reported TypeDoesNotContainType in a loop

Open ArtemGoutsoul opened this issue 1 year ago • 4 comments

Psalm started incorrectly reporting TypeDoesNotContainType some time after 5.19.1

Consider a two dimensional array, the code returns a count for each unique value in "key" column

/**
 * @param array{key: string}[] $array
 */
function func(array $array): array
{
    $r = [];
    foreach ($array as $row) {
        $r[$row['key']] = empty($r[$row['key']])
            ? 1
            : $r[$row['key']] + 1;
    }
    return $r;
}

psalm reports

Psalm output (using commit [c488d40](https://github.com/vimeo/psalm/commit/c488d40)): 

ERROR: [TypeDoesNotContainType](https://psalm.dev/056) - 10:27 - Operand of type false is always falsy

https://psalm.dev/r/707051b9f6

ArtemGoutsoul avatar Feb 16 '24 12:02 ArtemGoutsoul

I found these snippets:

https://psalm.dev/r/707051b9f6
<?php

/**
 * @param array{key: string}[] $array
 */
function func(array $array): array
{
    $r = [];
    foreach ($array as $row) {
        $r[$row['key']] = empty($r[$row['key']])
            ? 1
            : $r[$row['key']] + 1;
    }
    return $r;
}
Psalm output (using commit c488d40):

ERROR: TypeDoesNotContainType - 10:27 - Operand of type false is always falsy

psalm-github-bot[bot] avatar Feb 16 '24 12:02 psalm-github-bot[bot]

Not really a regression, you just weren't aware that psalm had a bug here in the first place: https://psalm.dev/r/64f874f2bc

$y shouldn't be '1|2|3' there, so this wasn't correctly checked by psalm before either.

kkmuffme avatar Feb 18 '24 11:02 kkmuffme

I found these snippets:

https://psalm.dev/r/64f874f2bc
<?php

/**
 * @param array{key: string}[] $array
 */
function func(array $array): array
{
    $r = [];
    foreach ($array as $row) {
        $y = $r[$row['key']];
        /** @psalm-trace $y */;
        
        $r[$row['key']] = empty($r[$row['key']])
            ? 1
            : $r[$row['key']] + 1;
    }
    return $r;
}
Psalm output (using commit c488d40):

INFO: Trace - 11:31 - $y: 1|2|3

ERROR: TypeDoesNotContainType - 13:27 - Operand of type false is always falsy

INFO: UnusedVariable - 10:9 - $y is never referenced or the value is not used

psalm-github-bot[bot] avatar Feb 18 '24 11:02 psalm-github-bot[bot]

@kkmuffme interesting!

I guess an earlier issue manifests differently now. But it's definitely a regression specifically for the use case I posted. It worked ok before, but fails now... But yeah, there's clearly some issue with type detection when an array is assigned in a loop.

ArtemGoutsoul avatar Feb 26 '24 16:02 ArtemGoutsoul