rfc:calls_in_constant_expressions
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
rfc:calls_in_constant_expressions [2020/02/09 02:42] – tandre | rfc:calls_in_constant_expressions [2020/03/04 13:56] – Withdrawn tandre | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Allow function calls in constant expressions ====== | ====== PHP RFC: Allow function calls in constant expressions ====== | ||
- | * Version: 0.1 | + | * Version: 0.5 |
- | * Date: 2020-02-20 | + | * Date: 2020-02-16 |
* Author: Tyson Andre < | * Author: Tyson Andre < | ||
- | * Status: | + | * Status: |
* First Published at: https:// | * First Published at: https:// | ||
Line 9: | Line 9: | ||
Currently, constant expressions in declarations allow a limited set of expression types such as literals, constants, and operations. | Currently, constant expressions in declarations allow a limited set of expression types such as literals, constants, and operations. | ||
- | This RFC proposes allowing calls of global functions in constant expressions | + | This RFC proposes allowing calls of a whitelist |
This will allow calling functions such as '' | This will allow calling functions such as '' | ||
An Error will be thrown if the call would be invalid to use within a constant (due to references or non-constant return values). | An Error will be thrown if the call would be invalid to use within a constant (due to references or non-constant return values). | ||
- | |||
- | Two secondary voting options are proposed for this: Allowing any function to be called, or allowing a small whitelist of deterministic functions. | ||
===== Proposal ===== | ===== Proposal ===== | ||
This RFC proposes allowing global function calls by name (in any namespace). | This RFC proposes allowing global function calls by name (in any namespace). | ||
- | Method | + | Method |
- | There are two secondary voting options | + | Function calls will be allowed |
- | These voting options reflect | + | |
- | Allowing any function to be called in a constant expression will allow more flexibility for users, | + | |
- | but limiting function names to a whitelist will make side effects of uses of constants easier to reason about when developers read php code. | + | |
- | The first option is to allow any function | + | * Defaults of static properties, but **not** instance properties, due to changes required to the PHP internals expanding the scope of this RFC too much. PHP currently evaluates all of the default values of instance properties of a class once, and permanently stores them. \\ This preserves PHP's current evaluation order (the first time a static property is used, all property default values are evaluated) |
- | leave it to coding practice guidelines to assert that constants are only | + | * Parameter defaults (expressions with function calls will always |
- | used in safe ways. | + | * Global |
+ | * Defaults of static variables (evaluated and cached the first time the expression succeeds) | ||
- | The second option is to only allow a whitelist functions that are actually deterministic and without side effects, and don't depend on ini | + | |
+ | Only functions in the following whitelist of functions will be callable in constant expressions. | ||
+ | Attempting | ||
+ | This whitelist | ||
settings or locale. The functions must be unambiguously resolved. | settings or locale. The functions must be unambiguously resolved. | ||
This has the same implementation as the first option, with additional compile-time restrictions. | This has the same implementation as the first option, with additional compile-time restrictions. | ||
Line 45: | Line 44: | ||
==== Behaviors in any constant expression ==== | ==== Behaviors in any constant expression ==== | ||
+ | |||
+ | Many of these edge cases aren't possible for functions in the whitelist, but will be checked for in the implementation. | ||
If a function call's result contains anything that is invalid for a constant (e.g. objects or reference cycles), | If a function call's result contains anything that is invalid for a constant (e.g. objects or reference cycles), | ||
- | an '' | + | an '' |
If a function call attempts to modify a parameter by reference, an '' | If a function call attempts to modify a parameter by reference, an '' | ||
Line 54: | Line 55: | ||
will all throw an '' | will all throw an '' | ||
- | Argument unpacking is allowed. (e.g. '' | + | Argument unpacking is allowed. (e.g. '' |
Function calls must be by name: | Function calls must be by name: | ||
Line 72: | Line 73: | ||
the first time they get used. | the first time they get used. | ||
- | Instance properties and parameter | + | Parameter |
Opcache is free to cache the result if the parameter values are known and the function is definitely deterministic. | Opcache is free to cache the result if the parameter values are known and the function is definitely deterministic. | ||
The behavior of constant expressions that don't contain function calls won't be modified by this RFC. | The behavior of constant expressions that don't contain function calls won't be modified by this RFC. | ||
- | |||
- | ==== Behaviors in Constant Expressions ==== | ||
- | |||
- | For class constants, static property defaults, and static variable defaults: | ||
- | If the evaluation of a constant expression throws, the result will not be cached. | ||
- | The expression will be evaluated repeatedly every time the constant expression gets used, | ||
- | and will get cached permanently the first time it doesn' | ||
==== Handling functions not in the whitelist ==== | ==== Handling functions not in the whitelist ==== | ||
- | A CompileError will be thrown | + | A fatal CompileError will be emitted |
<code php> | <code php> | ||
Line 110: | Line 104: | ||
const VALUES = [1, 0]; | const VALUES = [1, 0]; | ||
const C1 = count(self:: | const C1 = count(self:: | ||
- | const C2 = \count(self:: | + | const C2 = \COUNT(self:: |
const C3 = namespace\count(self:: | const C3 = namespace\count(self:: | ||
// const C4 = OtherNS\count(); | // const C4 = OtherNS\count(); | ||
Line 118: | Line 112: | ||
==== Whitelisted Functions ==== | ==== Whitelisted Functions ==== | ||
- | The following list of functions is proposed for the whitelist option of the secondary vote. | ||
Functions with the following properties were chosen. | Functions with the following properties were chosen. | ||
- | * Impossible to disable in unpatched php builds (e.g. '' | + | |
+ | | ||
* Reasonably deterministic (e.g. no file/ | * Reasonably deterministic (e.g. no file/ | ||
* Not dependent on locale or ini settings (e.g. '' | * Not dependent on locale or ini settings (e.g. '' | ||
Line 127: | Line 121: | ||
For this reason, '' | For this reason, '' | ||
- | The list of functions is below: | + | The following |
abs | abs | ||
Line 144: | Line 138: | ||
array_intersect_key | array_intersect_key | ||
array_intersect | array_intersect | ||
+ | array_key_exists | ||
array_key_first | array_key_first | ||
array_key_last | array_key_last | ||
Line 235: | Line 230: | ||
Opcache appears to be unaffected - tests of this RFC are passing. Opcache likely just fails to optimize the constant expressions ahead of time. | Opcache appears to be unaffected - tests of this RFC are passing. Opcache likely just fails to optimize the constant expressions ahead of time. | ||
- | In the future, if this gets adopted widely, | + | In the future, if this gets adopted widely, |
+ | |||
+ | Opcache already has the ability to optimize functions such as '' | ||
==== New Functions ==== | ==== New Functions ==== | ||
- | If the whitelist approach is used, '' | + | '' |
- | If any call is allowed in the secondary vote, that function won't be added. | + | |
===== Future Scope ===== | ===== Future Scope ===== | ||
Line 247: | Line 243: | ||
* Allowing even more expression types in constant expressions, | * Allowing even more expression types in constant expressions, | ||
- | * Adding more groups of functions to the whitelist, | + | * Adding more groups of functions to the whitelist, |
- | * Allowing non-constant defaults for instance properties, such as '' | + | * Allowing function calls in the defaults of instance properties. |
+ | * Allowing non-constant defaults for instance properties, such as '' | ||
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
Primary vote: Allow calling global functions that are in the described whitelist (Yes/No, Requires 2/3 majority) | Primary vote: Allow calling global functions that are in the described whitelist (Yes/No, Requires 2/3 majority) | ||
- | |||
- | Secondary vote: Allow calling any global functions, without a whitelist limitation (Yes/No, Requires 2/3 majority for " | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
Line 264: | Line 259: | ||
===== References ===== | ===== References ===== | ||
[[https:// | [[https:// | ||
+ | https:// | ||
rfc/calls_in_constant_expressions.txt · Last modified: 2020/03/04 14:01 by tandre