This is an old revision of the document!
PHP RFC: Make constructors and destructors return void
- Date: 2020-06-17
- Author: Benas Seliuginas, benas.molis.iml@gmail.com
- Target version: PHP 8.0
- Status: Under Discussion
Large credit for this RFC goes to Michael Voříšek who initially reported the bug and created a draft-- patch.
Introduction
At the moment, constructors and destructors can return values. However, these magic methods are supposed to be void (according to the documentation) and should not return a value. This RFC proposes to deprecate this behavior in PHP 8.0 and subsequently in PHP 9.0 enforce constructors and destructors having a return type of void.
This would apply both implicitly, where no return type is declared for the constructor/destructor, and explicitly where a void return type is declared.
Proposal
Status quo
Currently, void rules are not enforced for constructors and destructors. Thus, it is allowed to return values from those magic methods:
<?php class Test { public function __construct() { return 0; } public function __destruct() { return 1; } } $test = new Test(); // this prints 0 echo $test->__construct(); // this prints 1 echo $test->__destruct();
But the PHP manual states, that constructors have void return type (i. e. don't return a value). Therefore, the current behavior is inconsistent and incorrect. The void return type rule should always be enforced on constructors/destructors, no matter if the void return type declaration is implicit or explicit.
Proposal
This RFC proposes:
- to deprecate the ability of returning non-void values from constructors and destructors in PHP 8.0.
- to treat both contructors and destructors that do not have an explicit return type, as if they have a return type of void in PHP 9.0.
- to allow explicit void return type on constructors and destructors.
A deprecation warning would be generated:
- for any constructor or destructor that returns a value (<= PHP 8.0).
A fatal error would be generated:
- for any constructor or destructor that returns a value (>= PHP 9.0).
- for any constructor or destructor that has an explicit return type other than void.
<?php class Test { public function __construct() { // this is illegal // Fatal error: A void function must not return a value return 0; } // this is illegal // Fatal error: Destructor Test::__destruct() must return void public function __destruct(): mixed {} } class Test2 { // this is legal public function __construct(): void {} // this is also legal public function __destruct() {} }
Backward Incompatible Changes
Accepting this RFC results in a small backwards compatibility break in PHP 9.0 since it will no longer be legal to return non-void (mixed and any of its subtypes) values from constructors and destructors.
The position of this RFC is that this BC break is minimal, as returning values from contructors/destructors is not a standard pattern used by many pieces of code. However, to minimize the number of BC breaks even further, ability of returning non-void values from constructors/destructors is deprecated in PHP 8.0.
Unaffected Functionality
Explicit return type declaration is optional
Explicitly declaring the return type declaration would be optional. It would still be allowed to not specify a type at all:
<?php class Test { // this is legal public function __construct() {} // this is also legal public function __destruct(): void {} }
Constructors are exempt from inheritance checks
Since constructors are exempt from inheritance checks, it is allowed to widen the type from a child class. For example, if the parent class has explicitly declared the constructor as void, it would still be allowed to widen the type to no return type. In other words, covariance (for return types) does not apply to constructors.
<?php class Test { // this is legal public function __construct(): void {} } class Test2 extends Test { // this is also legal public function __construct() {} }
Vote
2/3 majority Yes/No.