rfc:arbitrary_static_variable_initializers

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:arbitrary_static_variable_initializers [2023/03/15 16:58] – Fix out-dated comment on ReflectionFunction::getStaticVariables() ilutovrfc:arbitrary_static_variable_initializers [2023/03/16 14:39] – Fix typos theodorejb
Line 26: Line 26:
 </code> </code>
  
-The right hand side of the assignment <php>static $i = 1;</php> must currently be a constant expressions. This means+The right hand side of the assignment <php>static $i = 1;</php> must currently be a constant expression. This means
 that it can't call functions, use parameters, amongst many other things. This limitation is hard to understand from a that it can't call functions, use parameters, amongst many other things. This limitation is hard to understand from a
 user perspective. This RFC suggests lifting this restriction by allowing the static variable initializer to contain user perspective. This RFC suggests lifting this restriction by allowing the static variable initializer to contain
Line 105: Line 105:
 foo(2); foo(2);
 var_dump((new ReflectionFunction('foo'))->getStaticVariables()['x']); var_dump((new ReflectionFunction('foo'))->getStaticVariables()['x']);
-// 2+// 1
 </code> </code>
  
Line 195: Line 195:
 // string(4) "Done", $i = 5, initializer not called // string(4) "Done", $i = 5, initializer not called
 </code> </code>
 +
 +==== What initializers are known at compile-time? ====
 +
 +In the discussion the question arose whether static variables depending on other static variables are known at compile time.
 +
 +<code php>
 +function foo() {
 +   static $a = 0;
 +   static $b = $a + 1;
 +}
 +</code>
 +
 +The answer is no. In this example it's clear that <php>$a</php> holds the value <php>0</php> until the initialization of <php>$b</php>. However, that's not necessarily the case. If <php>$a</php> is modified at any point between the two initializations the initial value of <php>$b</php> also changes.
 +
 +Here's a quick explanation of how this is implemented: During compilation of static variables the initializer AST is passed to the <php>zend_eval_const_expr</php> function. It traverses the AST and tries to compile-time evaluate all nodes by evaluating their children first and then the node itself if the child nodes were successfully evaluated. If the evaluation fails the nodes stay AST nodes and will again be evaluated at runtime when more information is available (e.g. when class constants are declared). These expressions are currently considered for compile-time constant expression evaluation:
 +
 +  * Literals (strings, ints, bools, etc)
 +  * Binary operations
 +  * Binary comparisons
 +  * Unary operations
 +  * Coalesce operator
 +  * Ternary operator
 +  * Array access (<php>self::FOO['bar']</php>)
 +  * Array literals
 +  * Magic constants (e.g. <php>__FILE__</php>)
 +  * Global constants (that are known at compile time)
 +  * Class constants (that are known at compile time)
  
 ===== Vote ===== ===== Vote =====
rfc/arbitrary_static_variable_initializers.txt · Last modified: 2023/05/24 18:29 by ilutov