rfc:void_return_type

This is an old revision of the document!


PHP 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 means to specify that no value can 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.

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; // Catchable fatal error: should_return_nothing() must not return a value, integer returned
}
should_return_nothing();

It accepts either an implicit return, or an explicit value-less return:

function lacks_return(): void {
    // valid
}
lacks_return();
 
function returns_nothing(): void {
    return; // valid
}
returns_nothing();

However, it does not accept returning a NULL value:

function returns_null(): void {
    return NULL; // Catchable fatal error: returns_null() must not return a value, null returned
}
returns_null();

This might seem odd given that return; is technically equivalent. However, allowing NULL would also allow this:

function returns_null2(): void {
    $x = some_computation(); // produces null most of the time
    return $x; // Catchable fatal error: returns_null() must not return a value, null returned
}
returns_null2();

If PHP were to allow returning a value which evaluates to null, we'd have to allow the above, and this doesn't make sense: a void function shouldn't be trying to return a value.

Furthermore, there is a code style point to be made here. return; signals different intent to return NULL;. The former returns control flow and, while it does implicitly produce a null return value, signals that the return value is unimportant. The latter, on the other hand, explicitly produces a null return value, suggesting that the null value is significant.

Like all functions which do not explicitly return a value in PHP, evaluating a call to a void return-typed function (“void function” from here onwards) results in null:

function summonElePHPants(): void {
    echo "ElePHPants of the world, unite!";
}
 
$useless_value = summonElePHPants();
var_dump($useless_value); // NULL

This is unlike void functions in some other languages, which prevent the use of such functions in expressions.

While it would be theoretically possible to prevent the use of void functions in expressions in PHP, this RFC does not do so for the following reasons:

  • PHP doesn't do this for built-in or extension PHP functions (aka “internal functions”) which return no value, and which are documented using “void”
  • For the entirety of PHP's history, all function calls have been valid expressions, and changing this will break code which relies on that fact
    • In particular, this would lead to unpredictable behaviour with callbacks
      • Passing along the result of a callback with return $somecallback(...); is a common pattern and would be broken by this change
    • Void return types could not be added to existing functions without possibly breaking code which calls them
  • This would introduce an unnecessary distinction between function call expressions and function call statements
  • This error cannot be caught at compile-time, because PHP is a dynamic language
  • Unlike all other return types, this would be placing a restriction on the caller
  • Implementing this in the Zend Engine would create problems:
    • This would require checking every function call to see whether its result is used, which could result in a slowdown for non-void calls
    • We currently do not have a mechanism to tell whether a function call's result is used - this would have to be added

Finally, IDEs and code linters could easily check for using the result of a void function call and warn the user, so it does not necessarily have to be enforced by the language itself.

The void type cannot be used for parameters:

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
    }
}

Backward Incompatible Changes

Like the scalar types proposed by the Scalar Type Hints RFC, the void return type does not become a reserved word, but is instead restricted from use in class and interface names. This avoids confusion while minimising backwards-compatibility breakage.

Proposed PHP Version(s)

This is proposed for the next major version of PHP, currently PHP 7.

Proposed Voting Choices

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.

Patches and Tests

There is a patch for php-src with tests here: https://github.com/php/php-src/pull/1084 It is based on patch used by the Scalar Type Hints RFC, since it already contains the infrastructure for reserving class and interface names for parameter and return types. However, should that RFC fail to pass, it would be possible to base the patch directly on master.

There is currently no patch for the language specification.

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged to
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature

Changelog

  • v0.1.1 - Detailed implicit null return value
  • v0.1 - Initial version
rfc/void_return_type.1423950251.txt.gz · Last modified: 2017/09/22 13:28 (external edit)