[RFC] Static variables in inherited methods

php.internals

Nikita Popov

5 years ago
Hi internals, While looking into various issues related to static variable handling, I've become increasingly convinced that our handling of static variables in inherited methods is outright buggy. However, it's also long-standing behavior, so I've put up an RFC: https://wiki.php.net/rfc/static_variable_inheritance Regards, Nikita

Dmitry Stogov

5 years ago
+1 On Tue, Feb 23, 2021 at 5:02 PM Nikita Popov <nikita.ppv@gmail.com> wrote:

A.L.E.C

5 years ago
On 23.02.2021 15:01, Nikita Popov wrote:
> While looking into various issues related to static variable handling, I've > become increasingly convinced that our handling of static variables in > inherited methods is outright buggy. However, it's also long-standing > behavior, so I've put up an RFC: > > https://wiki.php.net/rfc/static_variable_inheritance
What about non-static methods with static vars inside? I think it should be mentioned in the RFC, that it does not matter. Or the examples should not use a static method, for clarity. I'm not sure I would agree with the Traits behavior being consistent.
-- Aleksander Machniak Kolab Groupware Developer [https://kolab.org] Roundcube Webmail Developer [https://roundcube.net] ---------------------------------------------------- PGP: 19359DC1 # Blog: https://kolabian.wordpress.com

Nikita Popov

5 years ago
On Thu, Feb 25, 2021 at 9:48 AM Aleksander Machniak <alec@alec.pl> wrote:
> On 23.02.2021 15:01, Nikita Popov wrote: > > While looking into various issues related to static variable handling, > I've > > become increasingly convinced that our handling of static variables in > > inherited methods is outright buggy. However, it's also long-standing > > behavior, so I've put up an RFC: > > > > https://wiki.php.net/rfc/static_variable_inheritance > > What about non-static methods with static vars inside? I think it should > be mentioned in the RFC, that it does not matter. Or the examples should > not use a static method, for clarity. >
Thanks for the suggestion. I've explicitly mentioned that the behavior is independent of whether the method is static, and added an example.
> I'm not sure I would agree with the Traits behavior being consistent.
Yes, this part is not so clear cut. I think that intuitively, this is the correct behavior because it makes static variables work the same way as static properties. An additional consideration is that it's possible to use trait methods multiple times in the same class: <?php trait T { public static function counter() { static $i = 0; return ++$i; } } class A { use T { counter as counter1; counter as counter2; counter as counter3; } } var_dump(A::counter1()); var_dump(A::counter2()); var_dump(A::counter3()); I think it would be rather odd if A::counter1(), A::counter2(), A::counter3() all shared the same static variables, despite being distinct methods with distinct names. Regards, Nikita

Glash Gnome

5 years ago
Dears, Let me briefly introduce myself. I have been a C coder for 19 years, including 12 years with php. And I also do Java, C++, Javascript... from time to time. Nikita, What would the equivalent of this code be after RFC modification? <?php class CXPLeaks { static function refCount() { static $i=0; $i++; } function refCountByClass() { static $i=0; $i++; } function __construct() { self::refCount(); self::refCountByClass(); } } Declaring a static variable in a class or in a function, in terms of speed/work it's the same. For me, this is not a bug. It's a misunderstanding For me, who codes in C, the current behavior is intuitive. For me, there is no language as agile as PHP. Best regards, Serge PS: Updating the documentation would require less effort. And I propose to do so. I am already learning edit.php and PhD_PHP( [fr]language/control-structures/match.xml anonymous#2137) Le mar. 23 févr. 2021 à 15:02, Nikita Popov <nikita.ppv@gmail.com> a écrit :

Nikita Popov

5 years ago
On Thu, Feb 25, 2021 at 4:46 PM Glash Gnome <glash.gnome@gmail.com> wrote:
> Dears, > > Let me briefly introduce myself. I have been a C coder for 19 years, > including 12 years with php. And I also do Java, C++, Javascript... from > time to time. > > Nikita, What would the equivalent of this code be after RFC modification? > > <?php > > class CXPLeaks > { > static function refCount() { > static $i=0; > $i++; > } > function refCountByClass() { > static $i=0; > $i++; > } > function __construct() { > self::refCount(); > self::refCountByClass(); > } > } > > > Declaring a static variable in a class or in a function, in terms of > speed/work it's the same. > For me, this is not a bug. It's a misunderstanding > For me, who codes in C, the current behavior is intuitive. > For me, there is no language as agile as PHP. > > Best regards, > Serge >
Your example does not contain inheritance, so the RFC has no impact on it. As such, I do not understand your question. Nikita

Glash Gnome

5 years ago
I can understand that some people coming from C++, Java may be shocked by the behavior of a static variable in a static function. And the need to improve things. Maybe can you add *virtual static* keywords as a replacement for old behavior in your RFC <https://wiki.php.net/rfc/static_variable_inheritance> . You would satisfy me. class A { static function Counter() { static $count = 0; virtual static $i = 1; return [++$count, $i++]; } } class B extends A {} var_dump(A::Counter()); // array(int(1), int(1)) var_dump(A::Counter()); // array(int(2), int(2)) var_dump(B::Counter()); // array(int(3), int(1)) var_dump(B::Counter()); // array(int(4), int(2)) A::Counter::$count = 665; // Great Feature A::Counter::$i = 0; //Initialize B::Counter::$i = 0; //Reset In C Poo we could get : /*header*/ typedef struct _A {// Instance class A } A; typedef struct _AClass {// vtable class A int counter_i;// php: virtual static $i void (*counter)(void);// php: public static function counter(){} } AClass; typedef struct _B {// Instance class B A parent_instance; } B; typedef struct _BClass {// vtable class B AClass parent_class;// B contains its own virtual static variable $i } BClass; /*source*/ int A_counter_count = 0;// What did you expect ? //... A_counter_count = 665;// php: A::Counter::$count=665; A_class_entity.i = 0;// php: A::Counter::$i=0; B_class_entity.i = 0;// php: B::Counter::$i=0; Best regards, Serge Le mar. 23 févr. 2021 à 15:02, Nikita Popov <nikita.ppv@gmail.com> a écrit :

Nikita Popov

5 years ago
On Tue, Feb 23, 2021 at 3:01 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals, > > While looking into various issues related to static variable handling, > I've become increasingly convinced that our handling of static variables in > inherited methods is outright buggy. However, it's also long-standing > behavior, so I've put up an RFC: > > https://wiki.php.net/rfc/static_variable_inheritance >
I have now created an implementation for this change, and updated the RFC with some sample code for how one can preserve the old behavior, if it's being used deliberately. I plan to move forward with voting soon. Regards, Nikita

Alexandru Pătrănescu

5 years ago
On Wed, Mar 17, 2021 at 5:30 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Tue, Feb 23, 2021 at 3:01 PM Nikita Popov <nikita.ppv@gmail.com> wrote: > > > Hi internals, > > > > While looking into various issues related to static variable handling, > > I've become increasingly convinced that our handling of static variables > in > > inherited methods is outright buggy. However, it's also long-standing > > behavior, so I've put up an RFC: > > > > https://wiki.php.net/rfc/static_variable_inheritance > > > > I have now created an implementation for this change, and updated the RFC > with some sample code for how one can preserve the old behavior, if it's > being used deliberately. I plan to move forward with voting soon. >
Maybe it would be good to have links to some bug reports (that you mentioned) or a code snippet like this https://3v4l.org/J8Mme to clearly show that copying the static variable happens on inheritance point, with whatever that variable was at that point so it would be clear that the current behavior is undefined considering only B class, if it would be to ignore what happened to A in the meantime. Thanks, Alex

Nikita Popov

5 years ago
On Wed, Mar 17, 2021 at 5:48 PM Alexandru Pătrănescu <drealecs@gmail.com> wrote:
> > On Wed, Mar 17, 2021 at 5:30 PM Nikita Popov <nikita.ppv@gmail.com> wrote: > >> On Tue, Feb 23, 2021 at 3:01 PM Nikita Popov <nikita.ppv@gmail.com> >> wrote: >> >> > Hi internals, >> > >> > While looking into various issues related to static variable handling, >> > I've become increasingly convinced that our handling of static >> variables in >> > inherited methods is outright buggy. However, it's also long-standing >> > behavior, so I've put up an RFC: >> > >> > https://wiki.php.net/rfc/static_variable_inheritance >> > >> >> I have now created an implementation for this change, and updated the RFC >> with some sample code for how one can preserve the old behavior, if it's >> being used deliberately. I plan to move forward with voting soon. >> > > Maybe it would be good to have links to some bug reports (that you > mentioned) or a code snippet like this https://3v4l.org/J8Mme > to clearly show that copying the static variable happens on inheritance > point, with whatever that variable was at that point > so it would be clear that the current behavior is undefined considering > only B class, if it would be to ignore what happened to A in the meantime. > > Thanks, > Alex >
We already changed that behavior for PHP 8.1 independently of this RFC -- static variables will no longer depend on point of inheritance. This RFC is in addition to that change (and subsumes it really, because point of inheritance cannot matter anymore.) Regards, Nikita

Alexandru Pătrănescu

5 years ago
On Wed, Mar 17, 2021, 19:05 Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Wed, Mar 17, 2021 at 5:48 PM Alexandru Pătrănescu <drealecs@gmail.com> > wrote: > >> >> On Wed, Mar 17, 2021 at 5:30 PM Nikita Popov <nikita.ppv@gmail.com> >> wrote: >> >>> On Tue, Feb 23, 2021 at 3:01 PM Nikita Popov <nikita.ppv@gmail.com> >>> wrote: >>> >>> > Hi internals, >>> > >>> > While looking into various issues related to static variable handling, >>> > I've become increasingly convinced that our handling of static >>> variables in >>> > inherited methods is outright buggy. However, it's also long-standing >>> > behavior, so I've put up an RFC: >>> > >>> > https://wiki.php.net/rfc/static_variable_inheritance >>> > >>> >>> I have now created an implementation for this change, and updated the RFC >>> with some sample code for how one can preserve the old behavior, if it's >>> being used deliberately. I plan to move forward with voting soon. >>> >> >> Maybe it would be good to have links to some bug reports (that you >> mentioned) or a code snippet like this https://3v4l.org/J8Mme >> to clearly show that copying the static variable happens on inheritance >> point, with whatever that variable was at that point >> so it would be clear that the current behavior is undefined considering >> only B class, if it would be to ignore what happened to A in the meantime. >> >> Thanks, >> Alex >> > > We already changed that behavior for PHP 8.1 independently of this RFC -- > static variables will no longer depend on point of inheritance. This RFC is > in addition to that change (and subsumes it really, because point of > inheritance cannot matter anymore.) > > Regards, > Nikita >
Right, thanks for explaining. I remembered I saw it on mentioned somewhere but didn't know exactly where. Searched it now and it was this PR: https://github.com/php/php-src/pull/6705 Thank you, Alex