rfc:make_ctor_ret_void

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
rfc:make_ctor_ret_void [2020/06/17 21:39] – updated RFC moliatarfc:make_ctor_ret_void [2020/07/08 20:19] – updated RFC moliata
Line 3: Line 3:
   * Author: Benas Seliuginas, <benas.molis.iml@gmail.com>   * Author: Benas Seliuginas, <benas.molis.iml@gmail.com>
   * Target version: PHP 8.0   * Target version: PHP 8.0
-  * Status: Under Discussion+  * Status: Voting
  
 Large credit for this RFC goes to Michael Voříšek who initially reported the bug and created a draft-- patch. Large credit for this RFC goes to Michael Voříšek who initially reported the bug and created a draft-- patch.
  
 ===== Introduction ===== ===== 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.+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 ''void'' rules on constructors and destructors.
  
-This would apply both implicitly, where no return type is declared for the constructor/destructor, and explicitly where a void return type is declared.+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 ===== ===== Proposal =====
 ==== Status quo ==== ==== Status quo ====
-Currently, void rules are not enforced for constructors and destructors. Thus, it is allowed to return values from those magic methods:+Currently, ''void'' rules are not enforced for constructors and destructors. Thus, it is allowed to return values from those magic methods:
  
 <code php> <code php>
Line 36: Line 36:
 </code> </code>
  
-But the [[https://www.php.net/manual/en/language.oop5.decon.php|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.+But the [[https://www.php.net/manual/en/language.oop5.decon.php|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 ==== ==== Proposal ====
 This RFC proposes: This RFC proposes:
-  * to deprecate the ability of returning non-void values from constructors and destructors in PHP 8.0. +  * to deprecate the ability of returning 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 treat both constructors 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.+  * to allow explicit ''void'' return type on constructors and destructors (secondary vote).
  
 A deprecation warning would be generated: A deprecation warning would be generated:
-  * for any constructor or destructor that returns a value (<nowiki><=</nowiki> PHP 8.0).+  * for any constructor or destructor that returns a value in PHP 8.0 
 + 
 +Note: if there is an explicit ''void'' return type, a fatal error will be generated instead. This allows for newer codebases to take advantage of the check in PHP 8.0 already.
  
 A fatal error would be generated: A fatal error would be generated:
-  * for any constructor or destructor that returns a value (>PHP 9.0)+  * for any constructor or destructor that returns a value in PHP 9.0. 
-  * for any constructor or destructor that has an explicit return type other than void.+  * for any constructor or destructor that has an explicit return type other than ''void'' (secondary vote).
  
 <code php> <code php>
Line 56: Line 58:
  public function __construct() {  public function __construct() {
  // this is illegal  // this is illegal
- // Fatal error: A void function must not return a value 
  return 0;  return 0;
  }  }
  
- // this is illegal + // this is also illegal
- // Fatal error: Destructor Test::__destruct() must return void+
  public function __destruct(): mixed {}  public function __destruct(): mixed {}
 } }
  
 class Test2 { class Test2 {
- // this is legal+ // this is legal (secondary vote)
  public function __construct(): void {}  public function __construct(): void {}
  
Line 74: Line 74:
 </code> </code>
  
-===== Backward Incompatible Changes ===== +===== Backwards 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.+Accepting this RFC results in a small backwards compatibility break in PHP 9.0 since it will no longer be legal to return (''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.+The position of this RFC is that this BC break is minimal, as returning values from constructors/destructors is not a standard pattern used by many pieces of code. However, to minimize the number of BC breaks even further, the ability of returning values from constructors/destructors is deprecated in PHP 8.0.
  
-===== Unaffected Functionality =====+===== Unaffected functionality =====
 ==== Explicit return type declaration is optional ==== ==== 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: Explicitly declaring the return type declaration would be optional. It would still be allowed to not specify a type at all:
Line 95: Line 95:
  
 ==== Constructors are exempt from inheritance checks ==== ==== 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.+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.
  
 <code php> <code php>
Line 109: Line 109:
 } }
 </code> </code>
 +
 +===== Why allow void return type on constructors/destructors? =====
 +
 +**Enforcing ''void'' rules on constructors/destructors implictly but not allowing to declare an explicit type is going to create inconsistencies**.
 +
 +It's key to understand that constructors and destructors in PHP don't work the same way that they do in other languages. First of all, unlike in other languages, constructors and destructors are rather normal functions in PHP and can be called directly i. e. through ''$object-><nowiki>__</nowiki>construct()'' and ''$object-><nowiki>__</nowiki>destruct()''. Adding an explicit ''void'' return type acts as an extra marker that takes the reader from 99% certain to 100% that these functions are not supposed to return anything. This also aligns with the [[https://www.php.net/manual/en/language.oop5.decon.php|PHP manual]] which states that constructors/destructors have a return type of ''void'' and the Zen of Python's 2nd principle ("Explicit is better than implicit"). Thus, saying that other languages don't have a concept of return types for constructors does not make much sense in PHP's case.
 +
 +Rowan Tommins comment on the internals mailing list should also be taken into consideration:
 +"//The way I look at it, constructors are mostly declared like a normal
 +method - they use the keyword "function"; can be marked public, private,
 +protected, abstract, and final; and can have a parameter list, with
 +types and defaults - so the surprising thing is that there is a special
 +rule <nowiki>*forbidding*</nowiki> them from having a return specifier//".
 +
 +Another argument that is used against allowing explicit ''void'' return type is that it's going to create code-style wars and is duplicate information. But arguably, everyone also already knows what functions such as ''<nowiki>__</nowiki>toString()'' return. You know it's going to be a string. That's it's whole purpose. It would be surprising to see any code style forbidding that. Moreover, as of PHP 8.0, constructors and destructors will be the only methods that are not allowed to have a return type. This will be quite inconsistent given that ''<nowiki>__clone</nowiki>'' magic method will be able to have an explicit ''void'' return type even though both object construction and object cloning work in a similar fashion.
  
 ===== Vote ===== ===== Vote =====
-2/3 majority Yes/No.+Voting opened July 8th, 2020 and will close July 22nd, 2020. 
 + 
 +==== Primary ==== 
 +<doodle title="Make constructors/destructors return void?" auth="moliata" voteType="single" closed="false"> 
 +   Yes 
 +   * No 
 +</doodle> 
 + 
 +==== Secondary ==== 
 +<doodle title="Allow void return type on constructors/destructors?" auth="moliata" voteType="single" closed="false"> 
 +   * Yes 
 +   No 
 +</doodle>
  
 ===== Implementation ===== ===== Implementation =====
 [[https://github.com/php/php-src/pull/5727|GitHub Pull Request]] [[https://github.com/php/php-src/pull/5727|GitHub Pull Request]]
rfc/make_ctor_ret_void.txt · Last modified: 2020/07/22 15:29 by moliata