On 09/12/2025 13:59, Hichem Taboukouyout wrote:
Hello Internals of PHP,

I’d like to get feedback on a potential language feature before considering whether it deserves an RFC.

Currently, PHP does not provide a general way to distinguish between:
- a variable or property that has never been assigned, and
- one that was explicitly assigned the value null.


Hi Hichem,

This is something which has been discussed several times over the years, and consensus has generally been against.

My own view is largely unchanged since I wrote these two Stack Overflow answers a decade ago: https://stackoverflow.com/a/18646568/157957 and https://stackoverflow.com/a/18601583/157957


In short: any algorithm which needs to distinguish between "never assigned" and "currently contains null" can and should be rewritten to instead use some other distinction - a separate boolean tracking the state, or additional values which can be distinguished directly.

Key-value maps built with associative arrays or dynamic objects are an exception to this rule, but we already have array_key_exists and property_exists for those use cases.


One thing that has changed is that we now have native, opaque, enums; so many cases assigning specific meaning to null can be rewritten to be more expressive.

For example, instead of this:

```
/** @var ?string $inputFile */

if ( $inputFile === null ) {
    // do something with standard input
}
else {
    // verify and use the given input file in some way
}
```

You can write this:

```
enum InputFileOption { case STDIN; }

/** @var string|InputFileOption $inputFile */

if ( $inputFile === InputFileOption::STDIN ) {
    // do something with standard input
}
else {
    // verify and use the given input file in some way
}
```


Then instead of wanting a new "very null" check:

```
/** @var ??string $inputFile */

if ( ! is_assigned($inputFile) ) {
    // complain that the user didn't provide an answer
}
else if ( $inputFile === null ) {
    // do something with standard input
}
else {
    // verify and use the given input file in some way
}
```

You can just add a case to the enum:

```
enum InputFileOption { case STDIN; case NOT_CONFIGURED; }

/** @var string|InputFileOption $inputFile */

if ( $inputFile === InputFileOption::NOT_CONFIGURED ) {
    // complain that the user didn't provide an answer
}
else if ( $inputFile === InputFileOption::STDIN ) {
    // do something with standard input
}
else {
    // verify and use the given input file in some way
}
```


And unlike using "null" and "unassigned" for your special states, you can carry on adding more cases whenever you want.


Regards,

--
Rowan Tommins
[IMSoP]

Reply via email to