Table of Contents

PHP RFC: Transform void into an alias for null

Introduction

The void type was introduced in PHP 7.1 with the Void return type RFC. The motivation for introducing this type was to “specify that no value should be returned” for documentation and error-checking purposes.

Although in PHP, all functions return a value, the implicit default being null. The rationale for using void instead of null is laid out in the "Why call it void and not null?" subsection of the RFC.

Some have suggested that the return type be named null instead, since (as previously mentioned) PHP implicitly produces null as the result value for functions which don't explicitly return something, so void would be almost the same as just enforcing that a function returns null. Plus, void might suggest a function that can't be used in an expression, whereas null wouldn't. Also, void would be a new “type” in a sense, whereas null is preexisting.

The main reason to choose void over null is that it is the customary name to use for such a return type. We already use void rather than null when documenting functions in PHP [...] In addition, Hack, a PHP-derived and -compatible language [...] also uses void. [...] Since void seems to be the most popular choice for such a return type, both in PHP and elsewhere, why should we name it something different? There's no precedent for it and the name doesn't seem to have been an issue until now.

The other reason is that void more clearly conveys that the function is supposed to not return a value, rather than return null specifically.

Part of the proposal introducing void lays out the variance rules applying to void:

A void return type cannot be changed during inheritance. You can see this as either because return types are invariant, or because they are covariant and nothing is a subclass of void.

These variance rules were accurate at the time of the RFC. However, since PHP 7.1 various changes have been made to PHP's type system:

Thus, the variance semantics of void in PHP 8.4 are slightly different from those previously mentioned:

This means the following class hierarchy is valid:

<?php
 
class P {
    public function foo() {}
}
 
class C1 extends P {
    public function foo(): void {}
}
 
class CC1 extends C1 {
    public function foo(): never {}
}
 
class C2 extends P {
    public function foo(): mixed {}
}
 
class CC2 extends C2 {
    public function foo(): never {}
}
 
?>

This “split” type hierarchy where void is its own independent branch from the rest of the usual type system is rather nonsensical. Moreover, this means that a function without a defined return type is not isomorphic to one which defines a return type of mixed, something which is not the case for parameter types, as void is not a valid parameter type. This is a needless complication of PHP's type system that we argue should be removed.

Proposal

Transform void into a compile-time alias for null.

Backward Incompatible Changes

None.

Internal extensions that specify arg infos will have void types automatically normalized to null via the zend_normalize_internal_type() engine API.

All existing compile time errors and deprecations continue to be thrown or emitted, except:

Fatal error: A void function must not return a value (did you mean “return;” instead of “return null;”?)

For the following code:

function foo(): void {
    return null;
}

Which would now become valid as voidnull.

Version

Next minor version, PHP 8.5.

Vote

As per the voting RFC, a yes/no vote with a 2/3 majority is needed for this proposal to be accepted.

Voting started on 2025-XX-XX and will end on 2025-XX-XX.

Transform void into an alias for null?
Real name
Final result:
This poll has been closed.

Future scope

References