rfc:fetch_property_in_const_expressions

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:fetch_property_in_const_expressions [2022/06/23 10:53] – Rename RFC to clarify it only works on enums ilutovrfc:fetch_property_in_const_expressions [2022/07/18 21:57] (current) – Move to implemented ilutov
Line 2: Line 2:
   * Date: 2022-05-27   * Date: 2022-05-27
   * Author: Ilija Tovilo <ilutov@php.net>   * Author: Ilija Tovilo <ilutov@php.net>
-  * Status: Under discussion+  * Status: Implemented
   * Proposed Version: PHP 8.2   * Proposed Version: PHP 8.2
   * Implementation: https://github.com/php/php-src/pull/8625   * Implementation: https://github.com/php/php-src/pull/8625
Line 8: Line 8:
 ===== Introduction ===== ===== Introduction =====
  
-This RFC proposes to allow use of ''->''/''?->'' to fetch properties of enums in constant expressions. The primary motivation for this change is to allow fetching the ''name'' and ''value'' properties in places where enum objects aren't allowed, like array keys (see https://github.com/php/php-src/issues/8344). There is currently no way to express this without repeating the value of the enum case.+This RFC proposes to allow the use of ''->''/''?->'' to fetch properties of enums in constant expressions. The primary motivation for this change is to allow fetching the ''name'' and ''value'' properties in places where enum objects aren't allowed, like array keys (see https://github.com/php/php-src/issues/8344). There is currently no way to express this without repeating the value of the enum case.
  
 <PHP> <PHP>
Line 20: Line 20:
 ===== Proposal ===== ===== Proposal =====
  
-This RFC proposes to allow the use of ''->'' to fetch properties on enums inside all constant expressions. Using ''->'' on all other objects will result in a runtime error.+This RFC proposes to allow the use of ''->'' to fetch properties of enums inside all constant expressions. Using ''->'' on all other objects will result in a runtime error.
  
 Here are a few examples of code that will become valid if this RFC is accepted: Here are a few examples of code that will become valid if this RFC is accepted:
Line 48: Line 48:
 // The rhs of -> allows other constant expressions // The rhs of -> allows other constant expressions
 const VALUE = 'value'; const VALUE = 'value';
- 
 class C { class C {
      const C = E::Foo->{VALUE};      const C = E::Foo->{VALUE};
 } }
 </PHP> </PHP>
- 
-As mentioned, the primary motivation for this feature are enums. However, the implementation for supporting ''new'' is identical and I don't believe arbitrarily restricting how ''->'' can be used in this context makes sense. 
  
 For the sake of completeness, this RFC also adds support for the nullsafe operator ''?->''. For the sake of completeness, this RFC also adds support for the nullsafe operator ''?->''.
Line 60: Line 57:
 ===== Semantics ===== ===== Semantics =====
  
-The semantics of ''->'' in constant expressions are identical to outside of constant expressions, including access on non-object warnings, undefined property warnings, etc. One exception is that in constant expressions the operators may only be used on enums. The rationale for this decision is in "Supporting all objects".+The semantics of ''->'' in constant expressions are identical to outside of constant expressions, including access on non-object warnings, undefined property warnings, etc. One exception is that in constant expressions the operators may only be used on enums. The rationale for this decision is described in [[https://wiki.php.net/rfc/fetch_property_in_const_expressions#supporting_all_objects|Supporting all objects]].
  
 <PHP> <PHP>
Line 67: Line 64:
 } }
  
-// Warning: Undefined property: A::$c +class A {} 
-const = E::Foo->c; // NULL+ 
 +// Warning: Undefined property: E::$c 
 +const = E::Foo->c; // NULL
 // Note that this will change to an error in PHP 9 https://wiki.php.net/rfc/undefined_property_error_promotion // Note that this will change to an error in PHP 9 https://wiki.php.net/rfc/undefined_property_error_promotion
  
 // Warning: Attempt to read property "e" on null // Warning: Attempt to read property "e" on null
-const = (null)->e; // NULL+const = (null)->e; // NULL
  
 // Warning: Attempt to read property "" on null // Warning: Attempt to read property "" on null
 // Fatal error: Uncaught Error: Object of class A could not be converted to string // Fatal error: Uncaught Error: Object of class A could not be converted to string
-const = (null)->{new A};+const = (null)->{new A}
 + 
 +// Error: Fetching properties on non-enums in constant expressions is not allowed 
 +const C = (new A)->foo;
 </PHP> </PHP>
  
Line 82: Line 84:
  
 <PHP> <PHP>
-const = (null)?->b; // NULL +const = (null)?->prop; // NULL 
-const C = (null)?->d->e; // NULL +const C = (null)?->prop1->prop2; // NULL 
-const = (null)?->{new NotInstanciated}; // NULL +const = (null)?->{new NotEvaluated}; // NULL 
-const = (null)?->h['i']; // NULL+const = (null)?->prop['foo']; // NULL
 </PHP> </PHP>
  
Line 93: Line 95:
  
   - Order of evaluation   - Order of evaluation
-  - Cache invalidation+  - Caching of constant expression values 
 + 
 +Once we have a solution for these two problems we can extend support of ''->'' in constant expressions to all objects.
  
 ==== Order of evaluation ==== ==== Order of evaluation ====
Line 111: Line 115:
 </blockquote> </blockquote>
  
-The ''->'' suffers from the same problem as it may invoke the ''%%__get%%'' magic method with arbitrary side-effects. I incorrectly assumed this wasn't possible because ''%%__get%%'' can only be invoked in combination with ''new'' (as enums don't allow ''%%__get%%'') which are disallowed in these contexts. This assumption was incorrect though as the LHS of the ''->'' operator might be another constant which might be an object.+The ''->'' operator suffers from the same problem as it may invoke the ''%%__get%%'' magic method with arbitrary side-effects. I incorrectly assumed this wasn't possible because ''%%__get%%'' can only be invoked in combination with ''new'' (as enums don't allow ''%%__get%%'') which are disallowed in these contexts. This assumption was incorrect though as the LHS of the ''->'' operator might be another constant which might be an object.
  
 <PHP> <PHP>
Line 149: Line 153:
 [1] Ref-counted values consist of non-interned strings, arrays, resources and objects. [1] Ref-counted values consist of non-interned strings, arrays, resources and objects.
  
-==== Allow all ''readonly'' properties ====+==== Allow all readonly properties ====
  
-It was suggested thatinstead of restricting ''->'' to be used on all non-enums to restrict access to just non-''readonly'' properties. Unfortunately, this doesn't solve the caching problem described above as ''readonly'' properties can be initialized after object construction and thus becomes non-pure.+It was suggested that instead of restricting ''->'' to be used on all non-enums to restrict access to just non-''readonly'' properties. Unfortunately, this doesn't solve the caching problem described above as ''readonly'' properties can be initialized after object construction and thus becomes non-pure. The enum ''name'' and ''value'' properties are automatically initialized by the engine and thus are truly immutable.
  
 <PHP> <PHP>
Line 184: Line 188:
 ===== Vote ===== ===== Vote =====
  
-Voting opened on xxx and closes on xxx.+Voting opened on 2022-07-01 and closes on 2022-07-15.
  
 <doodle title="Add support for fetching properties of enums in constant expressions?" auth="ilutov" voteType="single" closed="true"> <doodle title="Add support for fetching properties of enums in constant expressions?" auth="ilutov" voteType="single" closed="true">
rfc/fetch_property_in_const_expressions.1655981621.txt.gz · Last modified: 2022/06/23 10:53 by ilutov