[RFC][Under discussion] Fetch properties in const expressions

  117815
May 28, 2022 09:44 tovilo.ilija@gmail.com (Ilija Tovilo)
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
  117825
May 29, 2022 16:23 larry@garfieldtech.com ("Larry Garfield")
On Sat, May 28, 2022, at 4:44 AM, Ilija Tovilo 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_expressions > > The 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
  117826
May 29, 2022 16:55 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Marcin_Brzuchalski?=)
niedz., 29 maj 2022 o 18:24 Larry Garfield <larry@garfieldtech.com>
napisał(a):

> On Sat, May 28, 2022, at 4:44 AM, Ilija Tovilo 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_expressions > > > > The 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. >
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
  117829
May 29, 2022 19:48 tovilo.ilija@gmail.com (Ilija Tovilo)
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
  117833
May 29, 2022 21:25 larry@garfieldtech.com (Larry Garfield)
May 29, 2022 11:55:56 AM Michał Marcin Brzuchalski brzuchalski@gmail.com>:

> > > niedz., 29 maj 2022 o 18:24 Larry Garfield <larry@garfieldtech.com> napisał(a): >> On Sat, May 28, 2022, at 4:44 AM, Ilija Tovilo 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_expressions >>> >>> The 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. > > 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
  118092
June 24, 2022 16:43 nicolas.grekas+php@gmail.com (Nicolas Grekas)
> > 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 > > 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
  118093
June 24, 2022 21:55 larry@garfieldtech.com ("Larry Garfield")
On Fri, Jun 24, 2022, at 11:43 AM, Nicolas Grekas 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_expressions >> > >> > The 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.) --Larry Garfield
  118100
June 27, 2022 07:38 marc@mabe.berlin (Marc Bennewitz)
On 24.06.22 23:55, Larry Garfield wrote:
> On Fri, Jun 24, 2022, at 11:43 AM, Nicolas Grekas 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_expressions >>>> >>>> The 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
  118103
June 27, 2022 08:16 rowan.collins@gmail.com (Rowan Tommins)
On 27/06/2022 08:38, Marc Bennewitz wrote:
> 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]
  118105
June 27, 2022 12:54 landers.robert@gmail.com (Robert Landers)
On Mon, Jun 27, 2022 at 10:16 AM Rowan Tommins collins@gmail.com> wrote:
> > On 27/06/2022 08:38, Marc Bennewitz wrote: > > 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] > > -- > PHP Internals - PHP Runtime Development Mailing List > 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
  117828
May 29, 2022 18:41 drealecs@gmail.com (=?UTF-8?Q?Alexandru_P=C4=83tr=C4=83nescu?=)
On Sat, May 28, 2022 at 12:44 PM Ilija 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_expressions > > The 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 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
  117832
May 29, 2022 20:40 nikita.ppv@gmail.com (Nikita Popov)
On Sat, May 28, 2022 at 11:44 AM Ilija 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_expressions > > The 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
  117846
June 2, 2022 12:17 tovilo.ilija@gmail.com (Ilija Tovilo)
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: > > > $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
  117849
June 3, 2022 13:26 landers.robert@gmail.com (Robert Landers)
On Thu, Jun 2, 2022 at 8:17 AM Ilija Tovilo ilija@gmail.com> wrote:
> > 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: > > > > > > > $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 > > -- > PHP Internals - PHP Runtime Development Mailing List > 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?
  117850
June 3, 2022 14:35 guilliam.xavier@gmail.com (Guilliam Xavier)
On Fri, Jun 3, 2022 at 3:26 PM Robert Landers robert@gmail.com> wrote:
> > 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?
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
  117947
June 14, 2022 16:13 tovilo.ilija@gmail.com (Ilija Tovilo)
Hi Robert, hi Guilliam

> > 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? > > 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
  117839
May 30, 2022 21:28 come@chilliet.eu (=?ISO-8859-1?Q?C=F4me_Chilliet?=)
Le 28 mai 2022 11:44:13 GMT+02:00, Ilija 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_expressions > >The 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: var; static $staticobj = new Thing(); function f($p = self::$staticobj->var) {} }
  117950
June 15, 2022 04:44 sji@sj-i.dev (shinji igarashi)
Hello!

Just a question.
Would this also be allowed?

https://3v4l.org/RGdIA
i;
    const ClassConstantViaPropertyFetching2 = B::ClassConstant->i;
}

Thanks!

--
Shinji Igarashi

2022年5月28日(土) 18:44 Ilija 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_expressions > > The RFC proposes adding support for fetching properties in constant > expressions using the -> operator. I'm looking forward to your > feedback. > > Regards, > Ilija > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php >
  117953
June 15, 2022 15:58 tovilo.ilija@gmail.com (Ilija Tovilo)
Hi

> Just a question. > Would this also be allowed? > > https://3v4l.org/RGdIA > > 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; > }
Yes, that would work fine. Ilija
  117954
June 15, 2022 17:04 drealecs@gmail.com (=?UTF-8?Q?Alexandru_P=C4=83tr=C4=83nescu?=)
On Wed, Jun 15, 2022 at 6:59 PM Ilija Tovilo ilija@gmail.com> wrote:

> Hi > > > Just a question. > > Would this also be allowed? > > > > https://3v4l.org/RGdIA > > > > > 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; > > } > > 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
  117956
June 15, 2022 23:54 sji@sj-i.dev (shinji igarashi)
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
  117971
June 16, 2022 22:46 tovilo.ilija@gmail.com (Ilija Tovilo)
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 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.
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
  118062
June 22, 2022 18:55 claude.pache@gmail.com (Claude Pache)
> Le 17 juin 2022 à 00:46, Ilija 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
  118067
June 23, 2022 04:23 drealecs@gmail.com (=?UTF-8?Q?Alexandru_P=C4=83tr=C4=83nescu?=)
On Fri, Jun 17, 2022 at 1:46 AM Ilija Tovilo ilija@gmail.com> wrote:

> 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
  118071
June 23, 2022 12:03 tovilo.ilija@gmail.com (Ilija Tovilo)
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