ajf

Andrea Faulds

Contents

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)

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.

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

  1. a link to the PHP manual entry for the feature

Versions

Version Changed Date
0.2.1 Add subsection explaining name choice
0.2 Revived, cleaned up proposal and rationale, added compile-time checking
0.1.1 Detailed implicit null return value
0.1 Initial version

Votes

An option needs 2/3 votes to win

Accept the Void Return Type RFC for PHP 7.1 and merge patch into master? (84.1% approved)
User Vote
aeoris Yes
aharvey No
ajf Yes
bishop Yes
brandon Yes
danack No
davey Yes
derick Yes
diegopires Yes
dm Yes
dragoonis Yes
francois Yes
galvao Yes
gasolwu Yes
guilhermeblanco Yes
hywan Yes
ircmaxell Yes
jgmdev Yes
kalle Yes
keyur Yes
kguest Yes
krakjoe Yes
levim No
lstrojny Yes
marcio No
mariano Yes
mbeccati Yes
mfonda No
mike Yes
nikic Yes
ocramius Yes
omars Yes
philstu Yes
rasmus Yes
rdlowrey Yes
reeze Yes
sebastian Yes
seld Yes
stas No
subjective Yes
svpernova09 Yes
tpunt Yes
trowski Yes
zimt No