psalm icon indicating copy to clipboard operation
psalm copied to clipboard

PossiblyUndefinedIntArrayOffset wrong for list

Open kkmuffme opened this issue 1 year ago • 5 comments

https://psalm.dev/r/55cf73b6a8 shouldn't give an error, as it's a list where keys are 0, 1, 2, 3,...

If any key is validated, any prior keys are automatically valid too.

kkmuffme avatar Sep 09 '22 04:09 kkmuffme

I found these snippets:

https://psalm.dev/r/55cf73b6a8
<?php

/**
 * @param list<string> $arg
 * @return void
 */
function foo( $arg ) {
    if ( isset( $arg[10] ) ) {
   		echo $arg[5];      
    }
   
}
Psalm output (using commit afe85fa):

INFO: PossiblyUndefinedIntArrayOffset - 9:11 - Possibly undefined array offset '5' is risky given expected type 'int'. Consider using isset beforehand.

psalm-github-bot[bot] avatar Sep 09 '22 04:09 psalm-github-bot[bot]

If isset($arg[10]) is true, it doesn't imply that isset($arg[5]) is also true:

php > $x = [10 => 1];
php > var_dump(isset($x[10]));
bool(true)
php > var_dump(isset($x[5]));
bool(false)

bor0 avatar Sep 10 '22 12:09 bor0

@bor0 your example is an associative array, not a list. This issue is purely for lists. See here what a list is: https://psalm.dev/docs/annotating_code/type_syntax/array_types/

kkmuffme avatar Sep 10 '22 14:09 kkmuffme

The issue here is a possibly not precise enough refinement: https://psalm.dev/r/a71c257367

The isset turns the list<string> into a array{10: string}<int, string>

This is technically correct but it's not the best way to store the new type. Instead, it should become a non-empty-list<string> and have the hidden property TNonEmptyList::$count set to 11 (maybe check the off by one here).

orklah avatar Sep 22 '22 18:09 orklah

I found these snippets:

https://psalm.dev/r/a71c257367
<?php

/**
 * @param list<string> $arg
 * @return void
 */
function foo( $arg ) {
    if ( isset( $arg[10] ) ) {
        /** @psalm-trace $arg */;
   		echo $arg[5];      
    }
   
}
Psalm output (using commit 028ac7f):

INFO: Trace - 9:33 - $arg: array{10: string}<int, string>

INFO: PossiblyUndefinedIntArrayOffset - 10:11 - Possibly undefined array offset '5' is risky given expected type 'int'. Consider using isset beforehand.

psalm-github-bot[bot] avatar Sep 22 '22 18:09 psalm-github-bot[bot]