Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Troubles with array_key_exists #10937

Open
BOPOH opened this issue May 3, 2024 · 4 comments
Open

Troubles with array_key_exists #10937

BOPOH opened this issue May 3, 2024 · 4 comments

Comments

@BOPOH
Copy link

BOPOH commented May 3, 2024

https://psalm.dev/r/ed6528a596

Copy link

I found these snippets:

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

/**
 * @psalm-return ?1
 */
function get_key(): ?int
{
    return null;
}

/**
 * @psalm-return 1
 */
function get_key_1(): int
{
    return 1;
}

function get_key_null(): null
{
    return null;
}

/**
 * @psalm-return array{1?: int, ''?: int}
 */
function get_keys(): array
{
    return [];
}

function test(int $value): int {
    return $value;
}

$keys = get_keys();
$key = get_key();
if (array_key_exists($key ?? '', $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[$key ?? ''] ?? 1);
}
if (array_key_exists((string)$key, $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[(string)$key] ?? 1);
}

$key = get_key_1();
if (array_key_exists($key, $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[$key] ?? 1);
}

$key = get_key_null();
if (array_key_exists($key ?? '', $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[$key ?? ''] ?? 1);
}
if (array_key_exists((string)$key, $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[(string)$key] ?? 1);
}

$key = '';
if (array_key_exists($key, $keys)) {
    /** @psalm-trace $keys */;
    /** @psalm-trace $key */;
    test($keys[$key] ?? 1);
}
Psalm output (using commit 08afc45):

INFO: Trace - 39:30 - $keys: array{''?: int, 1?: int}

INFO: Trace - 40:29 - $key: 1|null

ERROR: PossiblyUndefinedArrayOffset - 41:10 - Possibly undefined array key  on array{''?: int, 1?: int}

ERROR: PossiblyNullArgument - 41:10 - Argument 1 of test cannot be null, possibly null value provided

INFO: Trace - 44:30 - $keys: array{''?: int, 1?: int}

INFO: Trace - 45:29 - $key: 1|null

ERROR: PossiblyUndefinedArrayOffset - 46:10 - Possibly undefined array key  on array{''?: int, 1?: int}

ERROR: PossiblyNullArgument - 46:10 - Argument 1 of test cannot be null, possibly null value provided

INFO: Trace - 51:30 - $keys: array{''?: int, 1: int}

INFO: Trace - 52:29 - $key: 1

ERROR: TypeDoesNotContainType - 57:22 - Type null for $key is always !null

INFO: Trace - 58:30 - $keys: array{''?: int, 1?: int}

INFO: Trace - 59:29 - $key: null

ERROR: TypeDoesNotContainType - 60:16 - Type null for $key is always !null

INFO: Trace - 63:30 - $keys: array{''?: int, 1?: int}

INFO: Trace - 64:29 - $key: null

INFO: Trace - 70:30 - $keys: array{'': int, 1?: int}

INFO: Trace - 71:29 - $key: ''

@kkmuffme
Copy link
Contributor

kkmuffme commented May 3, 2024

Can you please describe what the issue is in a short text ?

@BOPOH
Copy link
Author

BOPOH commented May 6, 2024

@kkmuffme if array_key_exists($key, $array) returns true, then $key exists in array

i.e. if array_key_exists((string)$key, $keys) returns true, then $keys[(string)$key] exists, but psalm thows warning ERROR: [PossiblyUndefinedArrayOffset](https://psalm.dev/167) - 46:10 - Possibly undefined array key on array{''?: int, 1?: int} - that is the error

@kkmuffme
Copy link
Contributor

kkmuffme commented May 6, 2024

Happens because psalm does not store all evaluations but only variables. I don't think this will ever get fixed, especially since you can just assign $k = $key ?? ''; and use that instead of using the null coalesce twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants