Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressions
The RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.
Regards,
Ilija
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
Ilija
The enum-in-attribute use case came up recently in Symfony. I'm in favor and the RFC looks good to me.
--Larry Garfield
niedz., 29 maj 2022 o 18:24 Larry Garfield larry@garfieldtech.com
napisał(a):
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
IlijaThe enum-in-attribute use case came up recently in Symfony. I'm in favor
and the RFC looks good to me.
Personally, I'd start the discussion on
https://wiki.php.net/rfc/object_keys_in_arrays instead as this might solve
the need for
fetching property in constant expressions.
Cheers,
Michał Marcin Brzuchalski
Hi Michał
Personally, I'd start the discussion on
https://wiki.php.net/rfc/object_keys_in_arrays instead as this might solve
the need for
fetching property in constant expressions.
As mentioned in the RFC, supporting objects as array keys requires
much larger changes in the engine, and also breaks userland
assumptions that array keys can only be of type int|string which means
array functions need to handle object keys accordingly.
For comparison, the "object keys in arrays" RFC is incomplete (changes
for most extensions are missing) and contains ~1300 LOC added and
~1300 removed. All 3rd party PHP extensions would also need to be
updated accordingly. The implementation for this RFC is feature
complete and is at ~160 LOC added.
I actually think both of these RFCs are worthwhile, but since this one
is simpler and does not break userland assumptions it might solve the
problem in a good enough way.
HI Alexandru
I feel that the RFC should be named "Fetch properties in initializers", in sync with https://wiki.php.net/rfc/new_in_initializers
You explain what "constant expression" means but I feel that using "initialize expression" would be more clear.
From what I understand, "constant expression" is named like this because until PHP 8.1 it really was a constant.
And of course because internally this is how the functions in code are named:
- zend_is_allowed_in_const_expr
- zend_compile_const_expr
- zend_const_expr_to_zval
It's unclear how easy it would be to rename them to init_expr instead of const_expr
but it might be worth it if we consider that "initialize expression" is a better name.
Note that we also use the term constant expression in some error messages.
https://3v4l.org/d2WnS
I intentionally picked a static variable to show that it's not
restricted to consts. But I'm not attached to the term, if it's
clearer for other people I'm happy to switch to "initializer".
Regards,
Ilija
May 29, 2022 11:55:56 AM Michał Marcin Brzuchalski michal.brzuchalski@gmail.com:
niedz., 29 maj 2022 o 18:24 Larry Garfield larry@garfieldtech.com napisał(a):
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
IlijaThe enum-in-attribute use case came up recently in Symfony. I'm in favor and the RFC looks good to me.
Personally, I'd start the discussion on https://wiki.php.net/rfc/object_keys_in_arrays instead as this might solve the need for
fetching property in constant expressions.Cheers,
Michał Marcin Brzuchalski
Objects as array keys would not help with the attribute use case. It may be useful on its own, but it does not obviate the need for this rfc.
--Larry Garfield
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
IlijaThe enum-in-attribute use case came up recently in Symfony. I'm in favor
and the RFC looks good to me.
Genuine question:
In the thread about auto-implementing Stringable for string backed enums,
there is extensive argumentation to explain why ppl that use enums this way
are wrong. You mentioned writing a blog post about these reasons Larry, and
Benjamin (/cc) also expressed a similar opinion.
So my question is: don't these arguments apply here also? Shouldn't we
reject this RFC and tell ppl to use consts instead? If not, why?
Nicolas
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
IlijaThe enum-in-attribute use case came up recently in Symfony. I'm in favor
and the RFC looks good to me.Genuine question:
In the thread about auto-implementing Stringable for string backed enums,
there is extensive argumentation to explain why ppl that use enums this way
are wrong. You mentioned writing a blog post about these reasons Larry, and
Benjamin (/cc) also expressed a similar opinion.So my question is: don't these arguments apply here also? Shouldn't we
reject this RFC and tell ppl to use consts instead? If not, why?Nicolas
A fair question. :-) (Also, I'm working on said blog post literally as we speak.)
I'd say for many of the cases where the inability to use ->value has come up (eg, Attributes), a constant would indeed be the better solution. That's what people should probably be doing there.
However, while there are clear downsides to letting enums auto-coerce to strings (as discussed elsewhere), I don't really see a downside to this RFC. An enum case's value or name properties are guaranteed constant and readonly, so there's no reason I can see to not allow them to be used in a constant, readonly context. That it would allow someone to use SomeEnum::Beep->value in a place where it would probably be better to use SomeConst::Beep instead is a mostly-harmless side effect that doesn't violate any type expectations. And, if anything, the slight clunkiness of the syntax serves as an indicator that maybe you are doing it wrong and should be looking at something else.
So this patch is, in my mind, more about fleshing out a gap that fell through the cracks last version that happens to have a side effect of making connecting enums to pre-enum code possible, if a bit clunky. Auto-converting enums to other types is violating the domain model of different types and confusing their type spaces in semi-magical ways.
(Also, this is an understanding of the problem space I came to just in this past week, and hadn't fully chewed through when this RFC was first put forward.)
--Larry Garfield
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
Ilija
The enum-in-attribute use case came up recently in Symfony. I'm in favor
and the RFC looks good to me.Genuine question:
In the thread about auto-implementing Stringable for string backed enums,
there is extensive argumentation to explain why ppl that use enums this way
are wrong. You mentioned writing a blog post about these reasons Larry, and
Benjamin (/cc) also expressed a similar opinion.So my question is: don't these arguments apply here also? Shouldn't we
reject this RFC and tell ppl to use consts instead? If not, why?Nicolas
A fair question. :-) (Also, I'm working on said blog post literally as we speak.)I'd say for many of the cases where the inability to use ->value has come up (eg, Attributes), a constant would indeed be the better solution. That's what people should probably be doing there.
However, while there are clear downsides to letting enums auto-coerce to strings (as discussed elsewhere), I don't really see a downside to this RFC. An enum case's value or name properties are guaranteed constant and readonly, so there's no reason I can see to not allow them to be used in a constant, readonly context. That it would allow someone to use SomeEnum::Beep->value in a place where it would probably be better to use SomeConst::Beep instead is a mostly-harmless side effect that doesn't violate any type expectations. And, if anything, the slight clunkiness of the syntax serves as an indicator that maybe you are doing it wrong and should be looking at something else.
So this patch is, in my mind, more about fleshing out a gap that fell through the cracks last version that happens to have a side effect of making connecting enums to pre-enum code possible, if a bit clunky. Auto-converting enums to other types is violating the domain model of different types and confusing their type spaces in semi-magical ways.
(Also, this is an understanding of the problem space I came to just in this past week, and hadn't fully chewed through when this RFC was first put forward.)
Last week I run into this limitation - just sharing in case you would
see it a legitimate use case - not to say it can be done in another way:
I have defined classes for some public identifiers like UserId
.
These identifiers should be prefixed which I have defined as constant.
Now as I have a lot of such classes and I want to make sure all of the
prefixes are unique so I added an enum with all prefixes and use the
enum value as constant value as well.
enum IdPrefix:string
{
case USER_ID = 'u-';
// ...
}
class UserId extends AbstractPrefixedUid
{
public const PREFIX = IdPrefix::USER_ID->value;
}
Greetings,
Marc
Now as I have a lot of such classes and I want to make sure all of the
prefixes are unique so I added an enum with all prefixes and use the
enum value as constant value as well.enum IdPrefix:string
{
case USER_ID = 'u-';
// ...
}
This would never have occurred to me as a design, because I had no idea
that the values of backed enums were enforced to be unique. I'm not sure
if it can be considered "taking advantage of a side-effect", or if
people always expected backed enums to be used that way.
Ultimately, that's my reaction to both the enum-related RFC currently
under discussion: I don't really understand what backed enums are
intended for in the first place, so find it hard to judge whether
expanding them in a particular way makes sense. If a string-backed enum
can be considered just a unique set of strings, then it really has very
little in common with how I think of (unbacked) enums, but maybe that's
fine.
Regards,
--
Rowan Tommins
[IMSoP]
Now as I have a lot of such classes and I want to make sure all of the
prefixes are unique so I added an enum with all prefixes and use the
enum value as constant value as well.enum IdPrefix:string
{
case USER_ID = 'u-';
// ...
}This would never have occurred to me as a design, because I had no idea
that the values of backed enums were enforced to be unique. I'm not sure
if it can be considered "taking advantage of a side-effect", or if
people always expected backed enums to be used that way.Ultimately, that's my reaction to both the enum-related RFC currently
under discussion: I don't really understand what backed enums are
intended for in the first place, so find it hard to judge whether
expanding them in a particular way makes sense. If a string-backed enum
can be considered just a unique set of strings, then it really has very
little in common with how I think of (unbacked) enums, but maybe that's
fine.Regards,
--
Rowan Tommins
[IMSoP]--
To unsubscribe, visit: https://www.php.net/unsub.php
I think it is fair to consider backed enums a "set" vs. "enum." A good
use-case for integer-backed enums would be HTTP response codes,
however, the standard library only accepts integers
(http_response_code(), for example) and it would be nice if it either
accepted built-in enums or automatically cast integer-backed enums to
int. However, the latter probably makes more sense simply because
response codes are changing slightly, and will continue to evolve:
https://www.rfc-editor.org/rfc/rfc9110#section-15 (some 4xx codes have
been removed IIRC).
Robert Landers
Software Engineer
Utrecht NL
On Sat, May 28, 2022 at 12:44 PM Ilija Tovilo tovilo.ilija@gmail.com
wrote:
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.
I feel that the RFC should be named "Fetch properties in initializers", in
sync with https://wiki.php.net/rfc/new_in_initializers
You explain what "constant expression" means but I feel that using
"initialize expression" would be more clear.
From what I understand, "constant expression" is named like this because
until PHP 8.1 it really was a constant.
And of course because internally this is how the functions in code are
named:
- zend_is_allowed_in_const_expr
- zend_compile_const_expr
- zend_const_expr_to_zval
It's unclear how easy it would be to rename them to init_expr instead of
const_expr
but it might be worth it if we consider that "initialize expression" is a
better name.
The RFC looks great and clear.
Regards,
Alex
Regards,
Ilija--
To unsubscribe, visit: https://www.php.net/unsub.php
On Sat, May 28, 2022 at 11:44 AM Ilija Tovilo tovilo.ilija@gmail.com
wrote:
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
Ilija
This looks like a reasonable addition.
Could there be any expectation that if -> works, ?-> does as well?
Regards,
Nikita
Hi Nikita
This looks like a reasonable addition.
Could there be any expectation that if -> works, ?-> does as well?
Possibly. The implementation was simple enough so I'll add support for
completeness.
Hi Côme
It is not clear to me why this allows using -> on enums but not on other objects.
The RFC does allow using -> on all objects. From the RFC:
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.
Can you clarify why the following is not allowed:
<?php
$a = new Thing();
class C
{
protected $b = $a->var;
static $staticobj = new Thing();
function f($p = self::$staticobj->var) {}
}
protected $b = $a->var;
is not allowed because there can't be local
variables in the context of context expressions. function f($p = self::$staticobj->var) {}
is not allowed because static variables
aren't supported in constant expressions. Your examples would already
fail today without ->.
Ilija
Hi Nikita
This looks like a reasonable addition.
Could there be any expectation that if -> works, ?-> does as well?
Possibly. The implementation was simple enough so I'll add support for
completeness.
Hi Côme
It is not clear to me why this allows using -> on enums but not on other objects.
The RFC does allow using -> on all objects. From the RFC:
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.Can you clarify why the following is not allowed:
<?php
$a = new Thing();
class C
{
protected $b = $a->var;
static $staticobj = new Thing();
function f($p = self::$staticobj->var) {}
}
protected $b = $a->var;
is not allowed because there can't be local
variables in the context of context expressions.function f($p = self::$staticobj->var) {}
is not allowed because static variables
aren't supported in constant expressions. Your examples would already
fail today without ->.Ilija
--
To unsubscribe, visit: https://www.php.net/unsub.php
The RFC does allow using -> on all objects. From the RFC:
So, how does this change our mental models when writing PHP? For
example, I generally consider const
to be a "compile-time" constant
(ie, generated/created before any code is actually executed). So would
this allow code to actually execute before any other code (ie, by
putting code in a __get()) and thus cause issues due to database
drivers and etc to not be loaded yet -- or cause them to be loaded
prematurely?
So, how does this change our mental models when writing PHP? For
example, I generally considerconst
to be a "compile-time" constant
(ie, generated/created before any code is actually executed). So would
this allow code to actually execute before any other code (ie, by
putting code in a __get()) and thus cause issues due to database
drivers and etc to not be loaded yet -- or cause them to be loaded
prematurely?
True but that's already the case since PHP 8.1 and
https://wiki.php.net/rfc/new_in_initializers
(https://github.com/php/php-src/pull/7153), e.g.
https://3v4l.org/MSWi0:
class Foo {
public function __construct() {
echo "Side effect!\n";
}
}
const C = new Foo();
but as https://externals.io/message/113347#113607 says,
"side-effecting constructors are a terrible idea", and same can be
said for "side-effecting [magic] getters"...
Also note that this only concerns global (or namespace-scoped)
constants (which can also be defined "dynamically" with define()
),
not class constants.
--
Guilliam Xavier
Hi Robert, hi Guilliam
So, how does this change our mental models when writing PHP? For
example, I generally considerconst
to be a "compile-time" constant
(ie, generated/created before any code is actually executed). So would
this allow code to actually execute before any other code (ie, by
putting code in a __get()) and thus cause issues due to database
drivers and etc to not be loaded yet -- or cause them to be loaded
prematurely?True but that's already the case since PHP 8.1 and
https://wiki.php.net/rfc/new_in_initializers
(https://github.com/php/php-src/pull/7153), e.g.
https://3v4l.org/MSWi0:class Foo { public function __construct() { echo "Side effect!\n"; } } const C = new Foo();
Exactly. In fact, the only way you could invoke arbitrary userland
code through __get is in combination with new
, where side-effects
are already possible via constructor. Enums themselves don't allow
__get and thus can't lead to side-effects in constant expressions.
If there are no other concerns I'd like to open the voting phase by
the end of the week.
Ilija
Le 28 mai 2022 11:44:13 GMT+02:00, Ilija Tovilo tovilo.ilija@gmail.com a écrit :
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.
It is not clear to me why this allows using -> on enums but not on other objects.
Can you clarify why the following is not allowed:
<?php
$a = new Thing();
class C
{
protected $b = $a->var;
static $staticobj = new Thing();
function f($p = self::$staticobj->var) {}
}
Hello!
Just a question.
Would this also be allowed?
https://3v4l.org/RGdIA
<?php
class A {public int $i = 42;}
const BARE_CONSTANT = new A;
class B {
const ClassConstant = BARE_CONSTANT;
}
class C {
const ClassConstantViaPropertyFetching1 = BARE_CONSTANT->i;
const ClassConstantViaPropertyFetching2 = B::ClassConstant->i;
}
Thanks!
--
Shinji Igarashi
2022年5月28日(土) 18:44 Ilija Tovilo tovilo.ilija@gmail.com:
Hi everyone
I'd like to start a discussion on a simple RFC to allow fetching
properties in constant expressions.
https://wiki.php.net/rfc/fetch_property_in_const_expressionsThe RFC proposes adding support for fetching properties in constant
expressions using the -> operator. I'm looking forward to your
feedback.Regards,
Ilija--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi
Just a question.
Would this also be allowed?https://3v4l.org/RGdIA
<?phpclass A {public int $i = 42;}
const BARE_CONSTANT = new A;
class B {
const ClassConstant = BARE_CONSTANT;
}
class C {
const ClassConstantViaPropertyFetching1 = BARE_CONSTANT->i;
const ClassConstantViaPropertyFetching2 = B::ClassConstant->i;
}
Yes, that would work fine.
Ilija
Hi
Just a question.
Would this also be allowed?https://3v4l.org/RGdIA
<?phpclass A {public int $i = 42;}
const BARE_CONSTANT = new A;
class B {
const ClassConstant = BARE_CONSTANT;
}
class C {
const ClassConstantViaPropertyFetching1 = BARE_CONSTANT->i;
const ClassConstantViaPropertyFetching2 = B::ClassConstant->i;
}Yes, that would work fine.
Ilija
Hey, sorry to bump here on this topic.
My assumption was that the use of ->
in initializers would bear the same
limitations as using new
.
That would mean it would not be supported for
- class constant initializers
- instance property initializers
- static property initializers
For new
clarifications are here:
https://wiki.php.net/rfc/new_in_initializers#unsupported_positions
My assumption is that ->
would only work for:
- static variable initializers
- global constant initializers
- parameter default values
- attribute arguments
The examples shared by Shinji are for class constant initializers in class
C and I'm guessing it would not work.
If that's the case, I think we should clarify this in the RFC as well.
Regards,
Alex
Hello, Ilija, Alex,
Yes, that would work fine.
Thanks for the answer!
I am not opposed to this behavior, but it might be better to mention
it in the RFC.
Unlike Enums, an object in a constant can have mutable state, so the
result depends on when the constant expression is executed.
If it is difficult or doesn't have the benefit to determine the timing, it would
be better to clearly state that the timing of the execution of such constant
expression is undefined for now.
It is also an understandable behavior to prohibit the use of normal
objects in the property fetching in constant expressions because of the
difference in mutability between Enum and other objects.
That would mean it would not be supported for
- class constant initializers
- instance property initializers
- static property initializers
The new in initializers RFC doesn't explicitly mention the fact that
it allows class constants having objects via global constant, but
it's already doable in PHP 8.1.
class A {public int $i = 42;}
const BARE_CONSTANT = new A;
class B {
const ClassConstant = BARE_CONSTANT;
}
echo B::ClassConstant->i;
Thanks!
--
Shinji Igarashi
Hi Alexandru, hi Shinji
Hey, sorry to bump here on this topic.
My assumption was that the use of
->
in initializers would bear the same limitations as usingnew
.
That would mean it would not be supported for
- class constant initializers
- instance property initializers
- static property initializers
For
new
clarifications are here: https://wiki.php.net/rfc/new_in_initializers#unsupported_positionsMy assumption is that
->
would only work for:
- static variable initializers
- global constant initializers
- parameter default values
- attribute arguments
The examples shared by Shinji are for class constant initializers in class C and I'm guessing it would not work.
If that's the case, I think we should clarify this in the RFC as well.
Thank you for bringing this to my attention. I have missed the case
where, through constants, side-effects could be triggered in contexts
where they shouldn't.
class A {
public function __get($name) {}
}
const A = new A();
class B {
public $c = A->c;
}
I was under the incorrect impression that because (new A)->b is
disallowed in property initializers __get could never be triggered in
this context either but since the LHS of -> can be a constant
containing another object this is indeed possible. The problem is
described in the new in initializer RFC [1] you linked. There is
currently no appropriate place where evaluation of the expression
could happen without potential side-effects in places where we don't
want them, like unserialize.
Unfortunately, while thinking about this case I also discovered another issue.
class A {
public $b = 'b';
}
const A = new A;
class C {
public $b = A->b;
}
var_dump(new C());
$a = A;
$a->b = 'b2';
var_dump(new C());
Even without __get the property of an object referenced in the LHS of
the -> operator can change. The engine evaluates the default property
values once for the entire class and then copies the result whenever a
new instance of that class gets created. That means further instances
will use the out-dated property default value from when the first
instance was created. Similarly, function default parameters get
cached between calls. We could evaluate the constant expression for
each object instantiation or function call but degrading performance
for an edge case doesn't seem worth it.
Since the primary motivation of this RFC is to allow fetching the name
and value properties of enums I'm inclined to forbid using -> on
anything but enums. That would circumvent the issue since enums can't
contain user-defined properties nor the magic __get method, and
name/value are readonly.
I'll take a few days to think about the options, and will update the
RFC and inform the mailing list about the decision I have made. Let me
know if you have any more thoughts.
Ilija
[1] https://wiki.php.net/rfc/new_in_initializers#unsupported_positions
Le 17 juin 2022 à 00:46, Ilija Tovilo tovilo.ilija@gmail.com a écrit :
(...)
Since the primary motivation of this RFC is to allow fetching the name
and value properties of enums I'm inclined to forbid using -> on
anything but enums. That would circumvent the issue since enums can't
contain user-defined properties nor the magic __get method, and
name/value are readonly.I'll take a few days to think about the options, and will update the
RFC and inform the mailing list about the decision I have made. Let me
know if you have any more thoughts.
Hi,
I feel that, in any case, allowing unrestricted fetching properties in const expression in is semantically incorrect, because properties are fundamentally mutable. I am not speaking of creative use of code in order to achieve the effect, but of the regular semantics of properties.
For me, it seems reasonable to restrict the feature to readonly properties (including those of enums), because those are effectively immutable by design.
—Claude
Even without __get the property of an object referenced in the LHS of
The engine evaluates the default property
values once for the entire class and then copies the result whenever a
new instance of that class gets created. That means further instances
will use the out-dated property default value from when the first
instance was created. Similarly, function default parameters get
cached between calls. We could evaluate the constant expression for
each object instantiation or function call but degrading performance
for an edge case doesn't seem worth it.
Hey Ilija,
I really think we should have the same limitations for "->" and "?->" just
like we have for "new", with the same reason that that was disallowed.
That would mean not allowing it in the default values of a property.
Maybe I'm missing something but it looks like this was the plan all along
as you don't have any example that would include that, neither in the RFC
or in the PR tests.
The only case you mentioned and that's only in the RFC itself, not in PR
tests is the class constant for enums.
I'm not even sure that is working with the current implementation.
IMHO, allowing the fetch property operator in the 4 places where new is
allowed would be a simple good step forward.
There was the discussion where allowing it in attribute arguments is
important for allowing cross boundaries transforming from enum to string:
https://github.com/php/php-src/pull/8825#issuecomment-1161735119
An option to limit it to enums in the other 3 places, static or instance
property initializers and class constant initializers while allowing it on
all objects in the 4 cases where new is allowed.
Or yeah, limit to enum in all 7 cases, if that is a lot simpler.
I wouldn't prefer it as I still have cases in mind where I'm not dealing
with enums but it's your call.
Thank you,
Alex
Hi everyone
As foreshadowed in the last e-mail I updated the RFC to restrict the
fetching of properties to enums, and the PR to match it. Unless there
is more feedback I'd like to start the vote early next week.
https://wiki.php.net/rfc/fetch_property_in_const_expressions
Hi Claude
I feel that, in any case, allowing unrestricted fetching properties in const expression in is semantically incorrect, because properties are fundamentally mutable. I am not speaking of creative use of code in order to achieve the effect, but of the regular semantics of properties.
For me, it seems reasonable to restrict the feature to readonly properties (including those of enums), because those are effectively immutable by design.
I thought about this option before the last e-mail. Unfortunately
since readonly properties can be initialized after object construction
the same problem arises. You can find an example here:
https://wiki.php.net/rfc/fetch_property_in_const_expressions#allow_all_readonly_properties
Hi Alexandru
I really think we should have the same limitations for "->" and "?->" just like we have for "new", with the same reason that that was disallowed.
That would mean not allowing it in the default values of a property.
Maybe I'm missing something but it looks like this was the plan all along as you don't have any example that would include that, neither in the RFC or in the PR tests.
It was always planned to allow -> in all constant expressions. I added
tests now for all the constant expression positions. Now that only
enums are allowed I don't see a big reason for restricting the scope
any further.
An option to limit it to enums in the other 3 places, static or instance property initializers and class constant initializers while allowing it on all objects in the 4 cases where new is allowed.
Or yeah, limit to enum in all 7 cases, if that is a lot simpler.
I wouldn't prefer it as I still have cases in mind where I'm not dealing with enums but it's your call.
I mentioned in the last e-mail that there was an additional problem
regarding caching of constant expression results. I added a section to
the RFC (https://wiki.php.net/rfc/fetch_property_in_const_expressions#caching_of_constant_expression_values)
in an attempt to better explain this. I would rather delay support for
other objects until we're confident we have a good solution and
haven't missed any edge cases.
Regards,
Ilija