rfc:new_without_parentheses

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
rfc:new_without_parentheses [2024/04/23 07:57] – Added Other syntax ideas section vudaltsovrfc:new_without_parentheses [2024/05/28 18:04] (current) – Added Target Version vudaltsov
Line 3: Line 3:
   * Date: 2023-12-29   * Date: 2023-12-29
   * Author: Valentin Udaltsov (udaltsov.valentin@gmail.com)   * Author: Valentin Udaltsov (udaltsov.valentin@gmail.com)
-  * Status: Under Discussion+  * Status: Implemented 
 +  * Target Version: PHP 8.4
   * Discussion: https://externals.io/message/123031   * Discussion: https://externals.io/message/123031
   * First Published at: http://wiki.php.net/rfc/new_without_parentheses   * First Published at: http://wiki.php.net/rfc/new_without_parentheses
-  * Implementation and tests: https://github.com/php/php-src/pull/13029+  * Implementation: https://github.com/php/php-src/pull/13029
  
 ===== Introduction ===== ===== Introduction =====
Line 35: Line 36:
 ===== Proposal ===== ===== Proposal =====
  
-This RFC allows to omit parentheses around the ''new'' expression when constructor arguments' parentheses **are** present. Given class+This RFC allows to omit parentheses around the ''new'' expression **with** constructor arguments' parentheses. Given class
  
 <code php> <code php>
-class MyClass+class MyClass extends ArrayObject
 { {
     const CONSTANT = 'constant';     const CONSTANT = 'constant';
Line 59: Line 60:
     new MyClass()->method(),        // string(6)  "method"     new MyClass()->method(),        // string(6)  "method"
     new MyClass()(),                // string(8)  "__invoke"     new MyClass()(),                // string(8)  "__invoke"
 +    new MyClass(['value'])[0],      // string(5)  "value"
 ); );
  
Line 69: Line 71:
     new $myClass()->method(),        // string(6)  "method"     new $myClass()->method(),        // string(6)  "method"
     new $myClass()(),                // string(8)  "__invoke"     new $myClass()(),                // string(8)  "__invoke"
 +    new $myClass(['value'])[0],      // string(5)  "value"
 ); );
  
Line 78: Line 81:
     new (trim(' MyClass '))()->method(),        // string(6)  "method"     new (trim(' MyClass '))()->method(),        // string(6)  "method"
     new (trim(' MyClass '))()(),                // string(8)  "__invoke"     new (trim(' MyClass '))()(),                // string(8)  "__invoke"
 +    new (trim(' MyClass '))(['value'])[0],      // string(5)  "value"
 ); );
 </code> </code>
  
-This RFC still does not allow to omit parentheses around the ''new'' expression **without** constructor arguments' parentheses, because in some cases +This RFC does not change behavior of ''new'' expressions **without** constructor arguments' parentheses:
-this leads to an ambiguity:+
  
 <code php> <code php>
-// Instantiate and then access the instance or instantiate the result of the expression? +new MyClass::CONSTANT; // will continue to throw a syntax error 
-new MyClass::CONSTANT; +new $myClass::CONSTANT; // will continue to throw a syntax error 
-new MyClass::$staticProperty; +new MyClass::$staticProperty; // will continue to work as `new (MyClass::$staticProperty)` 
-new $myClass::CONSTANT; +new $myClass::$staticProperty// will continue to work as `new ($myClass::$staticProperty)` 
-new $myClass::$staticProperty; +new $myObject->property; // will continue to work as `new ($myObject->property)
-new $myClass->property; +new MyArrayConst['class']// will continue to throw a syntax error 
-new $myClass->method();+new $myArray['class']; // will continue to work as `new ($myArray['class'])`
 </code> </code>
  
Line 111: Line 114:
     // string(8) "__invoke"     // string(8) "__invoke"
     new class { public function __invoke() { return '__invoke'; } }(),     new class { public function __invoke() { return '__invoke'; } }(),
 +    // string(5) "value"
 +    new class (['value']) extends ArrayObject {}[0],
 ); );
 </code> </code>
Line 159: Line 164:
  
 ===== Other syntax ideas ===== ===== Other syntax ideas =====
 +
 +Some of the ideas expressed during the discussion of this RFC are listed below. They are orthogonal to this proposal and
 +require a separate RFC.
  
 ==== Allow to omit the new keyword ==== ==== Allow to omit the new keyword ====
  
-Some languages like Kotlin allow to instantiate class via [[https://onecompiler.com/kotlin/42b54ds4u|MyClass() expression]]. +Some languages like Kotlin allow to instantiate classes via [[https://onecompiler.com/kotlin/42b54ds4u|MyClass() expression]]. 
- +Omitting the "new" keyword in PHP is currently not possible, because classes and functions can [[https://3v4l.org/mfUVp|have the same name]] 
-Omitting the "new" keyword in PHP is currently not possible, because class and function names are case-insensitive. For example, one can declare +(in Kotlin [[https://onecompiler.com/kotlin/42b579yhu|it is not possible]]). Soin order to achieve this in PHP, we should first 
-class "Hello" and function "hello" in the same namespace. For ''new Hello()'', ''Hello::$prop'' and ''Hello::method()'' PHP will use the class. +deprecate declaring functions and classes with the same names.
-For ''hello()'' PHP will use the functionIf ''Hello()'' instantiation syntax is allowedPHP will have no idea what to choose.+
  
 ==== MyClass::new(), MyClass::create() ==== ==== MyClass::new(), MyClass::create() ====
  
-Introducing a dedicated static constructor like ''MyClass::new()'' or ''MyClass::create()'' would be a BC break for already +Introducing a dedicated static constructor like ''MyClass::new()'' or ''MyClass::create()'' would be a backward compatibility 
-existing static or object methods named ''new'' or ''create'' with required parameters and/or return type different from "static".+break for already existing static or object methods named ''new'' or ''create'' with required parameters and/or return 
 +type different from ''static''. So this idea also requires some deprecations.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 180: Line 188:
  
 PHP 8.4 PHP 8.4
 +
 +===== Proposed Voting Choices =====
 +
 +This is a simple yes-or-no vote to include this feature. 2/3 majority required to pass. 
 +
 +Voting started on 2024-05-09 and will end on 2024-05-24 00:00 GMT.
 +
 +<doodle title="Allow to omit parentheses around the new expression as described?" auth="vudaltsov" voteType="single" closed="true" closeon="2024-05-24T00:00:00Z">
 +   * Yes
 +   * No
 +</doodle>
 +
 +===== Implementation =====
 +
 +Pull request contains the final implementation and plenty of tests asserting the expected behavior and backward compatibility: https://github.com/php/php-src/pull/13029
 +
 +===== References =====
 +
 +  * [[https://externals.io/message/123031|This RFC discussion thread]]
 +
 +Old requests for this feature:
 +
 +  * [[https://externals.io/message/66197|Allow (...)->foo() expressions not only for `new` (see end of the page)]]
 +  * [[https://bugs.php.net/bug.php?id=70549|Allow `new Foo()->bar()` without parens around `(new Foo)`]]
 +  * [[https://externals.io/message/101811|Suggested change: change priority of new and ->]]
 +  * [[https://externals.io/message/113953|Raising the precedence of the new operator]]
 +
  
rfc/new_without_parentheses.1713859076.txt.gz · Last modified: 2024/04/23 07:57 by vudaltsov