rfc:constructor_promotion

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:constructor_promotion [2020/04/22 14:45] nikicrfc:constructor_promotion [2020/08/01 23:38] (current) – RFC was implemented carusogabriel
Line 2: Line 2:
   * Date: 2020-03-26   * Date: 2020-03-26
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
-  * Status: Under Discussion+  * Status: Implemented
   * Target Version: PHP 8.0   * Target Version: PHP 8.0
   * Implementation: https://github.com/php/php-src/pull/5291   * Implementation: https://github.com/php/php-src/pull/5291
Line 19: Line 19:
         float $x = 0.0,         float $x = 0.0,
         float $y = 0.0,         float $y = 0.0,
-        float $z = 0.0+        float $z = 0.0,
     ) {     ) {
         $this->x = $x;         $this->x = $x;
Line 39: Line 39:
         public float $x = 0.0,         public float $x = 0.0,
         public float $y = 0.0,         public float $y = 0.0,
-        public float $z = 0.0+        public float $z = 0.0,
     ) {}     ) {}
 } }
Line 91: Line 91:
 </PHP> </PHP>
  
-It is also not possible to use the ''callable'' type, because it is [[https://wiki.php.net/rfc/typed_properties_v2#callable_type|not supported]] as a property types:+It is also not possible to use the ''callable'' type, because it is [[https://wiki.php.net/rfc/typed_properties_v2#callable_type|not supported]] as a property type:
  
 <PHP> <PHP>
Line 160: Line 160:
 While repeating the default value on the property declaration would currently appear harmless, there are forward-compatibility reasons why it is preferable to only specify the default once. While repeating the default value on the property declaration would currently appear harmless, there are forward-compatibility reasons why it is preferable to only specify the default once.
  
-The first is a possible future extension to allow arbitrary expression in parameter and property defaults:+The first is a possible future extension to allow arbitrary expressions in parameter and property defaults:
  
 <PHP> <PHP>
Line 239: Line 239:
  
 As the example indicates, this allows using doc comment based annotations with promoted properties. As the example indicates, this allows using doc comment based annotations with promoted properties.
 +
 +Additionally, two new methods are added:
 +
 +  * ''ReflectionProperty::isPromoted()'' returns true for properties that have been implicitly generated as part of constructor promotion.
 +  * ''ReflectionParameter::isPromoted()'' returns true for parameters that have resulted in the generation of an implicit property as part of constructor promotion.
 +
 +Most reflection code should not care whether properties are generated or not, but this information will allow reconstructing the structure or the original code more easily.
  
 ==== Inheritance ==== ==== Inheritance ====
Line 248: Line 255:
     public function __construct(     public function __construct(
         protected Location $startLoc = null,         protected Location $startLoc = null,
-        protected Location $endLoc = null+        protected Location $endLoc = null,
     ) {}     ) {}
 } }
Line 260: Line 267:
         public bool $variadic = false,         public bool $variadic = false,
         Location $startLoc = null,         Location $startLoc = null,
-        Location $endLoc = null+        Location $endLoc = null,
     ) {     ) {
         parent::__construct($startLoc, $endLoc);         parent::__construct($startLoc, $endLoc);
Line 276: Line 283:
     public function __construct(     public function __construct(
         Location $startLoc = null,         Location $startLoc = null,
-        Location $endLoc = null+        Location $endLoc = null,
     ) {     ) {
         $this->startLoc = $startLoc;         $this->startLoc = $startLoc;
Line 297: Line 304:
         bool $variadic = false,         bool $variadic = false,
         Location $startLoc = null,         Location $startLoc = null,
-        Location $endLoc = null+        Location $endLoc = null,
     ) {     ) {
         $this->name = $name;         $this->name = $name;
Line 310: Line 317:
  
 It should be noted that the property assignments happen before the parent constructor is invoked. This is unusual in terms of coding style, but should not impact behavior for non-degenerate cases. It should be noted that the property assignments happen before the parent constructor is invoked. This is unusual in terms of coding style, but should not impact behavior for non-degenerate cases.
 +
 +==== Attributes ====
 +
 +As PHP 8 also introduces [[rfc:attributes_v2|attributes]], we need to consider how these features interact. Attributes are allowed both on properties and on parameters.
 +
 +<PHP>
 +class Test {
 +    public function __construct(
 +        <<ExampleAttribute>>
 +        public int $prop,
 +    ) {}
 +}
 +</PHP>
 +
 +This code could desugar in one of four ways:
 +
 +  - The attribute is applied only to the parameter.
 +  - The attribute is applied only to the implied property.
 +  - The attribute is applied both to the parameter and the property.
 +  - Attributes on promoted properties are forbidden, due to ambiguity.
 +
 +Here are the possible transformations:
 +
 +<PHP>
 +// Option 1: Attribute applies only to parameter.
 +class Test {
 +    public int $prop;
 +    
 +    public function __construct(
 +        <<ExampleAttribute>>
 +        int $prop,
 +    ) {}
 +}
 +
 +// Option 2: Attribute applies only to property.
 +class Test {
 +    <<ExampleAttribute>>
 +    public int $prop;
 +    
 +    public function __construct(
 +        int $prop,
 +    ) {}
 +}
 +
 +// Option 3: Attribute applies to both
 +class Test {
 +    <<ExampleAttribute>>
 +    public int $prop;
 +    
 +    public function __construct(
 +        <<ExampleAttribute>>
 +        int $prop,
 +    ) {}
 +}
 +
 +// Option 4: Error, cannot use attributes with constructor parameter promotion.
 +</PHP>
 +
 +This RFC proposes to use option 3 (applying the attribute to both property and parameter), as it is the most flexible. The ''isPromoted()'' Reflection APIs can be used by attribute validation code to discard the property or parameter attribute, if necessary.
 +
 +However, I consider this to be something of an implementation detail. If further work on attributes prior to the PHP 8 release shows that it would be advantageous to place the attribute only on the property, we should be open to such a change.
  
 ==== Coding Style Considerations ==== ==== Coding Style Considerations ====
Line 332: Line 400:
         public float $x = 0.0,         public float $x = 0.0,
         public float $y = 0.0,         public float $y = 0.0,
-        public float $z = 0.0+        public float $z = 0.0,
     ) {}     ) {}
 } }
Line 363: Line 431:
         float $x = 0.0,         float $x = 0.0,
         float $y = 0.0,         float $y = 0.0,
-        float $z = 0.0+        float $z = 0.0,
     ) {     ) {
         $this->x = $x;         $this->x = $x;
Line 381: Line 449:
  
 Larry provided some broader vision on how this feature can be combined with other features to improve our object initialization story in https://hive.blog/php/@crell/improving-php-s-object-ergonomics. Larry provided some broader vision on how this feature can be combined with other features to improve our object initialization story in https://hive.blog/php/@crell/improving-php-s-object-ergonomics.
- 
-Because constructor signatures that include promoted properties are likely to become long enough to require line-breaks, it would be beneficial to allow a trailing comma in function parameter lists: 
- 
-<PHP> 
-class Point { 
-    public function __construct( 
-        public float $x = 0.0, 
-        public float $y = 0.0, 
-        public float $z = 0.0, // <-- Allow this comma. 
-    ) {} 
-} 
-</PHP> 
- 
-Optional trailing commas in this position were previously declined, but I believe we have a stronger case for them nowadays, especially in conjunction with this feature. 
  
 ===== Prior Art ===== ===== Prior Art =====
Line 412: Line 466:
 ===== Vote ===== ===== Vote =====
  
-Yes/No.+Voting started 2020-05-15 and closes 2020-05-29. 
 + 
 +<doodle title="Add support for declaring properties in the constructor signature?" auth="nikic" voteType="single" closed="true"> 
 +   Yes 
 +   No 
 +</doodle>
  
rfc/constructor_promotion.1587566756.txt.gz · Last modified: 2020/04/22 14:45 by nikic