mago
mago copied to clipboard
Negated isset check should strongly assert that a key for a non-nullable type is absent
🐞 Describe the Bug
A !isset check on a specific array key tells us that the value in the array slot is either undefined or null. If the array shape for that array tells us that the type for that value is non-nullable, we should report it as definitely undefined, not just possibly undefined.
🔄 Steps to Reproduce
- Run
mago analyzeon the given example.
⚙️ Configuration (mago.toml)
php-version = "8.4.0"
[source]
paths = ["src"]
includes = ["vendor"]
excludes = []
📜 Command Output
❯ MAGO_LOG=trace cargo run -- --workspace play analyze src/nisset.php
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s
Running `target/debug/mago --workspace play analyze src/nisset.php`
2025-10-16T21:21:53.641632Z DEBUG main mago::config: Sourcing global configuration from /home/bsteinbrink/mago.toml.
2025-10-16T21:21:53.641700Z DEBUG main mago::config: Sourcing workspace configuration from play/mago.toml.
2025-10-16T21:21:53.644186Z INFO main mago::config: Overriding workspace directory with play.
2025-10-16T21:21:53.644208Z DEBUG main mago::config: Configuration specifies 32 threads.
2025-10-16T21:21:53.644218Z DEBUG main mago::config: Configuration specifies a stack size of 12582912 bytes.
warning[possibly-undefined-string-array-index]: Possibly undefined array key 'bar' accessed on `array{'bar'?: string}`.
┌─ src/nisset.php:7:24
│
7 │ var_dump($y['foo']['bar']); // This is reported as possibly-undefined although the type+check tells us it's definitely undefined
│ ^^^^^ Key 'bar' might not exist.
│
= The analysis indicates this specific key might not be set when this access occurs.
= Help: Ensure the key 'bar' is always set before accessing it, or use `isset()` or the null coalesce operator (`??`) to handle potential missing keys.
error[undefined-string-array-index]: Undefined array key 'baz' accessed on `array{'bar'?: string}`.
┌─ src/nisset.php:8:24
│
8 │ var_dump($y['foo']['baz']); // This is reported as undefined-string-array-index
│ ^^^^^ Key 'baz' does not exist.
│
= Attempting to access a non-existent string key will raise a warning/notice at runtime.
= Help: Ensure the key 'baz' exists before accessing it, or use `isset()` or the null coalesce operator (`??`) to handle potential missing keys.
error: found 2 issues: 1 error(s), 1 warning(s)
📂 PHP Code Sample (If Applicable)
<?php declare(strict_types=1);
/** @var array{ foo?: array{ bar?: string} } $y **/
$y = ['foo' => ['bar' => 123]];
if (isset($y['foo']) && !isset($y['foo']['bar'])) {
var_dump($y['foo']['bar']); // This is reported as possibly-undefined although the type+check tells us it's definitely undefined
var_dump($y['foo']['baz']); // This is reported as undefined-string-array-index
}
🖥️ Operating System
Linux
📦 How did you install Mago?
Built from Source
📝 Additional Context
No response
This might actually be a feature request 😅
Yea, this is not a bug. but it makes sense to implement.
repro: https://mago.carthage.software/playground#019b2a60-5a0d-a6e4-0848-fb9159458b96