rfc:new_in_initializers
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:new_in_initializers [2021/03/04 15:54] – nikic | rfc:new_in_initializers [2021/06/15 14:57] – nikic | ||
---|---|---|---|
Line 8: | Line 8: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | This RFC proposes to allow use of '' | + | This RFC proposes to allow use of '' |
Currently, code such as the following is not permitted: | Currently, code such as the following is not permitted: | ||
Line 36: | Line 36: | ||
This makes the actual default value less obvious (from an API contract perspective), | This makes the actual default value less obvious (from an API contract perspective), | ||
- | This RFC proposes to relax this restriction and allow the use of '' | + | This RFC proposes to relax this restriction and allow the use of '' |
===== Proposal ===== | ===== Proposal ===== | ||
- | '' | + | '' |
<PHP> | <PHP> | ||
Line 64: | Line 64: | ||
</ | </ | ||
- | Affected positions | + | New expressions |
<PHP> | <PHP> | ||
Line 70: | Line 70: | ||
const C = new Foo; | const C = new Foo; | ||
+ | |||
+ | function test($param = new Foo) {} | ||
# | # | ||
class Test { | class Test { | ||
- | | + | |
- | public | + | public $prop = new Foo, |
- | | + | |
} | } | ||
- | |||
- | function test($param = new Foo) {} | ||
</ | </ | ||
+ | |||
+ | ==== Unsupported positions ==== | ||
+ | |||
+ | New expressions continue to not be supported in (static and non-static) property initializers and class constant initializers. The reasons for this are twofold: | ||
+ | |||
+ | For non-static property initializers, | ||
+ | |||
+ | Performing the initialization by injecting code in the constructor avoids the issue, but requires that constructor to actually be called. In particular, this would necessitate generating constructors for classes that do not explicitly declare them, and the disciplined invocation of such constructors from potential parent constructors. The third option would be to introduce an additional initialization phase between creation and construction. | ||
+ | |||
+ | For static property initializers and class constant initializers a different evaluation order issue arises. Currently, these initializers are evaluated lazily the first time a class is used in a certain way. Once initializers can contain potentially side-effecting expressions, | ||
+ | |||
+ | The discussion has not yielded a satisfactory solution for these concerns, as such support in these contexts is delayed until such a time as a consensus on the preferred behavior can be reached. | ||
==== Order of evaluation ==== | ==== Order of evaluation ==== | ||
- | Initializer expressions could always contain side-effects through autoloaders or error handlers. However, support for '' | + | Initializer expressions could always contain side-effects through autoloaders or error handlers. However, support for '' |
* Static variable initializers are evaluated when control flow reaches the static variable declaration. | * Static variable initializers are evaluated when control flow reaches the static variable declaration. | ||
Line 89: | Line 101: | ||
* Attribute arguments are evaluated from left to right on every call of '' | * Attribute arguments are evaluated from left to right on every call of '' | ||
* Parameter default values are evaluated from left to right on every call to the function where the parameter is not explicitly passed. | * Parameter default values are evaluated from left to right on every call to the function where the parameter is not explicitly passed. | ||
- | * Property default values are evaluated in order of declaration (with parent properties before properties declared in the class) when the object is instantiated. This happens before the constructor is invoked. If an exception is thrown during evaluation, the object destructor will not be invoked. | ||
- | * The time of evaluation for static properties and class constants is unspecified. Currently, all static property and class constant initializers are evaluated on certain first uses of the class. (TODO?) | ||
- | ==== Interaction with reflection ==== | + | Additionally, initializers can be accessed through Reflection, in which case the following evaluation semantics apply: |
- | + | ||
- | Initializers, or values based on initializers, can be accessed through Reflection in various ways. This section specifies how the different methods behave: | + | |
* '' | * '' | ||
* '' | * '' | ||
* '' | * '' | ||
- | * '' | ||
- | * '' | ||
* '' | * '' | ||
- | * '' | ||
- | ==== Recursion protection | + | ==== Nested attributes |
- | If the evaluation of an object property default value results in recursion, an '' | + | It is worth mentioning explicitly that this RFC effectively adds support for nested attributes, which were omitted from the original attributes RFC. For example, attributes of the following form are now possible: |
<PHP> | <PHP> | ||
- | class Test { | + | # |
- | public $test = new Test; | + | |
- | } | + | |
- | + | ||
- | new Test; | + | |
- | // Error: Trying to recursively instantiate Test while evaluating default value for Test::$test | + | |
</ | </ | ||
- | |||
- | ==== Trait property compatibility ==== | ||
- | |||
- | When two traits declaring the same property are used in a class, a compatibility check is performed, which requires that both use the same initializer. Consider the following example: | ||
- | |||
- | <PHP> | ||
- | trait T1 { | ||
- | public $prop = new A; | ||
- | } | ||
- | trait T2 { | ||
- | public $prop = new A; | ||
- | } | ||
- | |||
- | class B { | ||
- | use T1, T2; | ||
- | } | ||
- | </ | ||
- | |||
- | These properties are not compatible, because trait compatibility is determined using identity comparison ('' | ||
- | |||
- | Initializer expressions are separated into two categories: Non-dynamic (all existing expression types) and dynamic (containing '' | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
- | None. | + | This RFC does not introduce any backwards-incompatible changes, and also should not break any major assumptions. The only case where something genuinely new is possible are nested attributes. |
===== Future Scope ===== | ===== Future Scope ===== |
rfc/new_in_initializers.txt · Last modified: 2021/07/14 07:19 by nikic