PHP RFC: Void Return Type
- Version: 0.2.1
- Date: 2015-02-14 (v0.1, later withdrawn), 2015-10-14 (v0.2, revival)
- Author: Andrea Faulds, ajf@ajf.me
- Status: Implemented (PHP 7.1)
- First Published at: http://wiki.php.net/rfc/void_return_type
Introduction
The Return Types RFC has introduced return types to PHP. While there is already a means to specify that any value may be returned (by omitting the return type), there is no way to specify that no value should be returned, unlike many other languages with return types. This is unfortunate, as this can be useful for documentation and error-checking purposes. In particular, it makes it clear that a function performs an action, rather than producing a result. This RFC proposes the introduction of a void
return type for this purpose, similar to that in other programming languages.
Proposal
Support for a new void
return type is added. It requires that a function not return any value:
function should_return_nothing(): void { return 1; // Fatal error: A void function must not return a value }
Unlike other return types which are enforced when a function is called, this type is checked at compile-time, which means that an error is produced without the function needing to be called.
A function with a void
return type, or void function, may either return implicitly, or have a return statement without a value:
function lacks_return(): void { // valid }
function returns_nothing(): void { return; // valid }
A void function may not return a value:
function returns_one(): void { return 1; // Fatal error: A void function must not return a value }
function returns_null(): void { return null; // Fatal error: A void function must not return a value }
Note that void
is only valid as a return type, not as a parameter type:
function foobar(void $foo) { // Fatal error: void cannot be used as a parameter type }
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
.
class Foo { public function bar(): void { } } class Foobar extends Foo { public function bar(): array { // Fatal error: Declaration of Foobar::bar() must be compatible with Foo::bar(): void } }
Rationale
Why check at compile-time?
Generally-speaking, you should warn of problems sooner rather than later. It just so happens that it's trivial (a three-line change) to make PHP to check this at compile-time rather than run-time. So, this proposal suggests just that.
Why isn't ''return null;'' permitted?
Some people have asked about this, since return;
and return null;
are technically equivalent in PHP; when a return value isn't specified, PHP will produce null
for you. However, choosing one over the other suggests intent. If you specify a value, it suggests the value is significant. In a void function, the return value is insignificant: it's always the same and has no actual usefulness. Specifying it explicitly with return null;
is pointless, because it doesn't really matter what value the function is going to return.
Since void
signifies an unimportant return value that won't be used, this proposal requires you to not specify one. This extends to null
just as it does to any other value.
Use of void functions in expressions
In some other languages, such as C, a void function can't be used in an expression, only as a statement. Since this RFC adds a way to specify a void function to PHP's syntax, it might be expected the same restriction would now apply in PHP. However, this wouldn't match precedent. PHP has had 'void functions' of a kind since its inception, in the form of built-in functions, which are documented as “void” in the manual. Such functions can be used in expressions, unlike in C.
We could change PHP's rules on void functions and disallow their use in expressions, but this would create a backwards-compatibility issue: it's not inconceivable that existing PHP code relies on being able to call built-in void functions in expressions, and plenty of code assumes that you can take the return value of an arbitrary PHP function (a callback, perhaps).
Moreover, IDEs and other tools can warn the user when the return value of a void function is being used. It isn't strictly necessary for the language itself to cover this.
Why call it void and not null?
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 preëxisting.
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, both built-in and userland functions: PHP's function prototypes in source code (e.g.), the PHP manual (e.g.) and phpDocumentor's docblock format (see definition) all use void
. In addition, Hack, a PHP-derived and -compatible language which adds its own typing system, also uses void. This is just looking at existing PHP practice; most contemporary programming languages use void
here. Some of these (C, Objective-C and C++, Java, C#, etc.) prohibit the use of a void function in an expression, but note that others (TypeScript, ActionScript, Swift) do allow void functions in expressions, just as PHP does, by making them implicitly return some unit type. 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.
Backward Incompatible Changes
Like the names reserved by the Scalar Type Declarations and Reserve More Types in PHP 7 RFCs, the void
return type does not become a reserved word proper, but is instead prohibited from use as the name of a class or interface. This avoids confusion while minimising backwards-compatibility issues. I do not expect that Void
is a very common class name, and so the backwards-compatibility impact should be limited.
Proposed PHP Version(s)
This is proposed for the next minor version of PHP, currently PHP 7.1.
Vote
As this is a language change, a 2/3 majority is required. The vote is a straight Yes/No vote for accepting the RFC and merging the patch.
Voting started 2015-10-29 and ended 10 11 days later on 2015-11-09.
Patches and Tests
There is a patch for php-src's master branch with tests: https://github.com/php/php-src/pull/1576
There is also a patch for the language specification's master branch with tests: https://github.com/php/php-langspec/pull/150
Implementation
The patch for the Zend Engine was merged into php-src master here: https://github.com/php/php-src/commit/366ba41334870f325f248d8e486e3ebf8bafb984
The patch for the language specification was merged into master here: https://github.com/php/php-langspec/commit/ad1a8bdba48ed23f118fe743f6930d1d57cd8042
The feature will go into PHP 7.1.
After the project is implemented, this section should contain
- a link to the PHP manual entry for the feature
Changelog
- v0.2.1 - Add subsection explaining name choice
- v0.2 - Revived, cleaned up proposal and rationale, added compile-time checking
- v0.1.1 - Detailed implicit null return value
- v0.1 - Initial version