Fix GH-10497: Allow const obj->prop = value#20903
Conversation
iluuu1994
left a comment
There was a problem hiding this comment.
Thanks @khaledalam! Looks reasonable overall.
Thanks @iluuu1994 for the feedback, all comments addressed. |
|
Cool, thanks @khaledalam! This is a language change and should be discussed on the internals mailing list at least. I think this will impact GH-13800, but that's not a major issue. |
|
Btw, one thing in particular people might object to is: const arrayTest = [1, 2, 3];
arrayTest[] = 4;
var_dump(arrayTest);This becomes valid, but prints: I.e. the assignment has no effect, because it happens on a temporary value. Make sure to mention this in your e-mail to internals. |
|
I've opened an internals thread and sent an email for discussion: https://news-web.php.net/php.internals/129757 |
|
It sounds like @TimWolla objected, so this would need an RFC, or at least the mitigation from https://news-web.php.net/php.internals/129839. |
TimWolla
left a comment
There was a problem hiding this comment.
Yes, my replies on the list were an objection against the PR as-is. Selecting request changes for visibility.
|
Noted, I'll look into it |
d488d10 to
b0a2437
Compare
Pass type parameter to zend_compile_const() instead of bool use_tmp Check BP_VAR_R/BP_VAR_IS for read mode Remove unnecessary wrapper function Return void instead of zend_op*
b0a2437 to
2bd4eb9
Compare
Description
Fixes #10497 - Allows direct modification of object properties stored in constants, for both global constants and class constants.
RFC: https://wiki.php.net/rfc/const_object_property_write
Problem
Previously, this code would fail with a fatal error:
Solution
In zend_delayed_compile_prop(), when the object expression is a constant used in a write context (BP_VAR_W/RW/UNSET/FUNC_ARG), fetch the constant at runtime instead of treating it as a temporary:
Because the constant is fetched at runtime (not compile-time evaluated), the property write targets the real object.
The constant binding itself is never modified.
Scope
Supported:
Still rejected (unchanged):
Backward incompatible change
Enum cases are class constants, so they're affected. Writing to or unsetting a readonly case property, e.g. unset(Enum::Case->value) or Enum::Case->value = x , now raises the standard runtime readonly-property Error instead of the previous compile-time "Cannot use temporary expression in write context" fatal. This matches plain variable access ($x = Enum::Case; unset($x->value);). Enum case properties remain immutable.