Hi Gina
On Mon, Jun 2, 2025 at 6:28 PM Gina P. Banyard <internals@gpb.moe> wrote:
RFC: PHP: rfc:void-as-null
After a read, I think I fundamentally disagree with the proposal. It
says (regarding the status-quo):
* void is not a subtype of a function with a mixed return type
This is laid out as a downside, but I don't think it is. Consider this
example under the specified behavior:
interface MapInterface {
public function set(string $key, mixed $value): void;
}
class Map implements MapInterface {
public function set(string $key, mixed $value): void {
// Store the key/value pair _somehow_
}
}
Let's assume the return type `MapInterface::set()` `mixed` instead,
where the intention is for `set()` to return the previous value, or
`null` if there was none. This change will go completely unnoticed by
`Map::set()`, because `void` is now just `null`, which is a subtype of
`mixed`. This is a bug that would previously have been caught,
notifying you that you're supposed to return _something_.
Similarly, the code `function foo(): void { return null; }` is now
proposed to be valid, and I assume the inverse for `void`/`return;` is
also true. In this example, we now update `Map::set()` to the new
return type.
class Map implements MapInterface {
public function set(string $key, mixed $value): mixed {
$oldValue = /* Fetch old value _somehow_ */;
// Store the key/value pair _somehow_
if (!$this->observers) {
return; // This line was here before.
}
$this->observers->notify($key, $oldValue, $value);
return $oldValue;
}
}
Good examples are hard, but imagine `Map::set()` would allow notifying
a list of observers about changes to the map. Previously, the
`return;` would have prevented an erroneous call to `notify()` on
`null`. However, now it is missing the returning of `$oldValue`. This
is another bug that would previously have been caught. In fact, even a
missing trailing `return $something;` would not be caught anymore.
IMO, these checks are useful enough not to be removed.
Please let me know if I'm missing anything.
Ilija