Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123926 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id D92AC1A009C for ; Thu, 27 Jun 2024 06:11:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1719468794; bh=/TTCpbemaIc5gmXCWM5nnq9Ty0b4wpiv26AOavUs1tk=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=HMxxSpnq9kLg4/NHms6zuSOGpPvITM4g+TAwR9TPRvFS+8KP26aPqzhA5l15X+UKt /fW01diasoLo1YTL0ZOfgc7nhmajQr7+1sJJAxMcGe1EyVbLcomugxm+AYLVZQU9em IK94iP3rwhiouCxYv0h7ZMZ6FEFEFhKm5wOZStyVENm/VCsKMwsus5qZJCDZ+O88RL 1jJiJ7G5uB4yW/hKe91/KVCBO3bM3ce+WFEPIoPovQDTs1L5wqwWCr7UrU+4jSeR97 FJmMMUIT3/YVgVd/KWPzGNdu3TOk+t1Ni5O9J23SJbPm3oOltk99yt1Y5tRhSjSfjA JmuZ5jBlP/Rpg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 439B71804F3 for ; Thu, 27 Jun 2024 06:13:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-yb1-f169.google.com (mail-yb1-f169.google.com [209.85.219.169]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 27 Jun 2024 06:13:12 +0000 (UTC) Received: by mail-yb1-f169.google.com with SMTP id 3f1490d57ef6-df4d5d0b8d0so6925971276.2 for ; Wed, 26 Jun 2024 23:11:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20230601.gappssmtp.com; s=20230601; t=1719468714; x=1720073514; darn=lists.php.net; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=Nqv7DRfpDxaRYXnh0BMXGn/jkaOlpyYBI97BHtYOuaQ=; b=CIl1Dtng+lKOIbT+OZWXnKmwj0TwqCstB6sd7OkcWWUsXLNXeRjUYR7FLRdnsL/YVS Lw4FvvRXdStNeqnbNmTQDoOSwnGhG0AgDascBz5ysajMUl4XBC2OBw9prxwyYElCF7Mj h69w0ygwzCxlbO4D6kBnzEIR/ztmlKP3iizIpwXxuvJZI/CiYSfwzB14rYHWkPSQPT9P IcoX80+HYxWLMJj0RvkRFoSiVcSbFneXrjsJRKarqOfX0kJiVQ7eKshwYUhyO6Cn9NLv iTfGIpLF/3b7CFIYvtZLVWYUuTgPiGaHzVHN6q3RkC0phSRMhf/LI+buFMGIh1lVZeT2 TBkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719468714; x=1720073514; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Nqv7DRfpDxaRYXnh0BMXGn/jkaOlpyYBI97BHtYOuaQ=; b=gYAIAX/xQlmiMtScJ8nYx0w2KxHDZsegNsorlX5nZeqGJe9Z6GevHhgXoREfM1c+08 Kpg2D0nd3HxAokhkhqvdBOk9BxW0F+33jP2dLRyABKhfcb4mcg+qDt3pcmD/0EUcmmtJ 8fwy2+krzqszSzjv/10AehBRbwpcaxWZGckYNQSMjjnmKUzreB3v1489VD10fGFyxR6S ncmAVfZ8DnpaKHNl8azc3mMPjJA+/i8NlWlQaea2e7cj+uj+N+9gybg/+ccZECEon9dq BGJ7fVbntceYXP79GUf7C+mDSfGFsmBRBB2W6EsOINaFxCjPlpby9/Zi8PvUYbUouRNW IyRQ== X-Forwarded-Encrypted: i=1; AJvYcCXjSb13bSYjS4HoXHHoNh0oMh+B23clm1xsx9sY6HIBecdA+9+jwPjCMwalDOgBuUAIo1B5Q+7DIROnhOYEfug70bG2Isw1+A== X-Gm-Message-State: AOJu0YzqCYpNUVjqPc9RJgqw6YZbywJ7M21EKtbekNEGRA6S499eLb1J 3ycnxqHdrwWK+gSLITp//+66DF3z2ilcK392mYfPpqK3TBJU82V41uLrkCiBPQaMSp3GWaWmHae GsDk= X-Google-Smtp-Source: AGHT+IEwOR+biVOyf081waYlyozZdaU3I4yg3jJAKOkp/oTP1/azfDbdPCxFd48CBCimNDjgxPsGgg== X-Received: by 2002:a05:6902:1b12:b0:dff:2ce8:cc1b with SMTP id 3f1490d57ef6-e0303f530fbmr13198665276.35.1719468713702; Wed, 26 Jun 2024 23:11:53 -0700 (PDT) Received: from smtpclient.apple (c-98-252-216-111.hsd1.ga.comcast.net. [98.252.216.111]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e0345b98714sm130968276.36.2024.06.26.23.11.52 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Jun 2024 23:11:52 -0700 (PDT) Message-ID: <94425545-7066-4D2B-BAA2-65CDE7117E56@newclarity.net> Content-Type: multipart/alternative; boundary="Apple-Mail=_7B1473CB-DB97-4F08-90FE-56340668A018" Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.8\)) Subject: Re: [PHP-DEV] [RFC] Static class Date: Thu, 27 Jun 2024 02:11:51 -0400 In-Reply-To: <97BA9681-FA0A-4929-A6F4-67DF4820ADBF@koalephant.com> Cc: Claude Pache , php internals To: Stephen Reay References: <88D83E92-94BE-4548-B398-8F5C74765FFD@gmail.com> <882BD9E0-42E9-4C84-A144-7C1DFC4CE5EB@newclarity.net> <662F259B-D125-48EA-8AA0-1DC8BECA4C09@newclarity.net> <97BA9681-FA0A-4929-A6F4-67DF4820ADBF@koalephant.com> X-Mailer: Apple Mail (2.3696.120.41.1.8) From: mike@newclarity.net (Mike Schinkel) --Apple-Mail=_7B1473CB-DB97-4F08-90FE-56340668A018 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Jun 27, 2024, at 12:09 AM, Stephen Reay = wrote: >=20 > Hi Mike, >=20 > To answer your question: I believe `abstract static` should be = allowed, because the "objection" mis-characterises a particular aspect = of them as an unintended consequence, when there's evidence to show = that's not that case. >=20 > Claude essentially dismisses the use of abstract static methods: >=20 >>> only consequences of their intended meaning on non-static class >=20 > In v5.2 a strict standards notice was added regarding the use of = abstract static methods in classes. No notice was ever shown when = they're used in interfaces. In v7 this notice was removed (via = https://wiki.php.net/rfc/reclassify_e_strict#abstract_static_methods = ) = because, as Nikita noted at the time: Thank you for elaborating.=20 We are on the same page here as I too think `abstract static` should be = allowed when declaring a class >> We currently allow the use of abstract static functions in = interfaces, as such it is inconsistent to not allow them as abstract = methods. By using late static binding a method in the abstract class can = reasonably depend on the existence of a static method in a superclass.=20= >=20 >=20 > That to me says this is an intended feature, and not an unintended = consequence. Before I address this and your other comments, please understand that I = do not see this as a huge issue either way, but I do want my argument to = be understood. If my argument on this does not win the day, I will not = lament it in any way. As an aside, I had never seen interfaces used that way and found it = surprising. Obviously I missed when Nikita made that claim. =20 As for "an intended feature, and not an unintended consequence," when I = was in university they drilled the idea of a sunken cost into me to the = point I am a true believer. IOW, make the best decision moving forward = vs. doubling down on bad decisions.=20 Note that I am not saying Nikita's was a bad decision (or a good one) = just that the existence of a prior decision should not color making the = best decision moving forward. I am curious, do you know of real-world userland code that is actually = configured as your example that would be negatively affected by = disallowing static methods calls? > On Jun 26, 2024, at 4:26 AM, Stephen Reay > wrote: >=20 > This is an example of code that works today (and all the way back to = 5.0): https://3v4l.org/4EKo2 The class hierarchy = embody the type of classes this RFC is about: only static members, no = instantiation.=20 >=20 > The *implemented methods* can be called statically, regardless of = whether the class they're implemented in is abstract or not. The = *abstract methods* cannot be called directly. Understood, but I do not see how interfaces or instantiation or abstract = method are relevant to the discussion. They all seem orthogonal to me. > So these classes would be a candidate for the `static` class keyword = (or Attribute) - except they can't, if calls to implemented methods on = abstract classes are disallowed. Because the Base::a() method has been = publicly callable, for potentially as long as 20 years = next month. While it may be true that it has been that way, disallowing `static = methods` from being called using `abstract static` classes would not be = a BC break because it was previously impossible to declare a class as = `static` let alone `abstract static`. Further, there are often new features with constraints that result in = developer not being "to do what they have been able to do for 20 years" = because, looking forward, those constraints make more sense than not = having those constraints.=20 Take a look at `readonly` properties. They must be typed, but I could = have used the same argument against that saying "We've always been able = to have untyped properties so readonly should not have to be typed."[1] = I'd say requiring them to be typed was a win, though, regardless of past = property capabilities. I'm not claiming necessarily that disallowing calling `static` methods = on a `abstract static` class is a best practice, but I am saying that = "we've been able to do it with similar syntax for a long time" is not a = particularly compelling argument if disallowing is a better approach. As another aside, assuming everyone agrees on what a best practice is = for a given case, I doubt anyone would object to a constraint that = forced developers to follow that best practice vs. allowing them to = write less ideal code. > My point here is that if someone wants to prohibit calling public = static methods on abstract classes *with* the static keyword, that's = going be inconsistent with how it's worked for the last 20 years (i.e. = on classes that were 'static' in intent but not syntactically), Back to sunken cost, does it make more sense to only give developers who = want to disallow using static methods for their `abstract static` = classes access to `@internal docblock` =E2=80=94 which I argued against = elsewhere in this thread =E2=80=94 and let Hyrum's Law take over, OR do = we enable them to disallow calling those `static` methods from the = `abstract` class itself? More importantly, IF we do not immediately disallow calling `static` = methods on `abstract static` classes then we will never be able to = disallow in the future, because of BC. But on the flip side we could = later open them up for calling if we found the limitation to be = problematic. > or if it applies the change everywhere it's going to be a BC break. And to be clear, I am against BC breaks in almost all cases. So bringing = that up between us is moot. All that said, if you tell me "I don't care about closing the door on = being able to disallow developers from calling static methods on = `abstract static` methods because prior to `abstract static` classes = `static` methods could be called on `abstract` classes in the past" I = will respect that, and as I said above, it won't bother me. =20 My only reason for persisting is to ensure that the argument I was = making was understood before it was dismissed. -Mike [1] Ignoring there were technical issues with allowing untyped to be = readonly, which could have been gotten around somehow if the consensus = was "They must be able to untyped." --Apple-Mail=_7B1473CB-DB97-4F08-90FE-56340668A018 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On = Jun 27, 2024, at 12:09 AM, Stephen Reay <php-lists@koalephant.com> wrote:

Hi Mike,

To answer your question: I believe `abstract static` = should be allowed, because the "objection" mis-characterises a = particular aspect of them as an unintended consequence, when there's = evidence to show that's not that case.

Claude essentially dismisses the use of = abstract static methods:

only consequences of their intended meaning on non-static = class

In v5.2 a strict standards notice was = added regarding the use of abstract static methods in classes. No notice = was ever shown when they're used in interfaces.  In v7 this notice = was removed (via https://wiki.php.net/rfc/reclassify_e_strict#abstract_static_me= thods) because, as Nikita noted at the = time:

Thank = you for elaborating. 

We are on = the same page here as I too think `abstract static` should be allowed = when declaring a class

We = currently allow the use of abstract static functions in interfaces, as = such it is inconsistent to not allow them as abstract methods. By using = late static binding a method in the abstract class can reasonably depend = on the existence of a static method in a = superclass. 

That to me says this is an intended = feature, and not an unintended = consequence.

Before I address this and your other comments, = please understand that I do not see this as a huge issue either way, but = I do want my argument to be understood. If my argument on this does not = win the day, I will not lament it in any way.

As an aside, I had never seen = interfaces used that way and found it surprising. Obviously I missed = when Nikita made that claim.  

As for "an intended = feature, and not an unintended consequence," when I was in = university they drilled the idea of a sunken cost into me to the point I = am a true believer. IOW, make the best decision moving = forward vs. doubling down on bad decisions. 

Note that I am not = saying Nikita's was a bad decision (or a good one) = just that the existence of a prior decision should not color making the = best decision moving forward.

I am curious, do you know of real-world = userland code that is actually configured as your example that would be = negatively affected by disallowing static methods calls?

On Jun 26, 2024, at 4:26 AM, Stephen Reay <php-lists@koalephant.com> wrote:

This is an example of code that = works today (and all the way back to 5.0): https://3v4l.org/4EKo2
The class hierarchy embody the type of classes this RFC is = about: only static members, no = instantiation. 

The *implemented = methods* can be called statically, regardless of whether the class = they're implemented in is abstract or not. The *abstract methods* cannot = be called directly.

Understood, = but I do not see how interfaces or instantiation or abstract method are = relevant to the discussion. They all seem orthogonal to me.

So these classes would be a = candidate for the `static` class keyword (or Attribute) - except they = can't, if calls to implemented methods on abstract classes are = disallowed. Because the Base::a() method has been publicly callable, for = potentially as long as <checks notes>  20 years next = month.

While it may be true that it has been that way, = disallowing `static methods` from being called using `abstract static` = classes would not be a BC break because it was previously impossible to = declare a class as `static` let alone `abstract static`.

Further, there are often = new features with constraints that result in developer not being "to do what they have been able to do for 20 years" = because, looking forward, those constraints make more sense than not = having those constraints. 

Take a look at `readonly` properties. = They must be typed, but I could have used the same argument against that = saying "We've always been able to have untyped properties = so readonly should not have to be typed."[1] I'd say requiring them to be = typed was a win, though, regardless of past = property capabilities.

I'm not claiming necessarily that = disallowing calling `static` methods on a `abstract static` class is a best practice, but I am saying that "we've been able to do it with similar syntax for a long = time" is not a particularly compelling argument if disallowing is a = better approach.

As another aside, assuming everyone agrees on what a best = practice is for a given case, I = doubt anyone would object to a constraint that forced developers to = follow that best practice vs. allowing them to write less ideal = code.

My point here is that if = someone wants to prohibit calling public static methods on abstract = classes *with* the static keyword, that's going be inconsistent with how = it's worked for the last 20 years (i.e. on classes that were 'static' in = intent but not syntactically),

Back to sunken cost, = does it make more sense to only give developers who want to disallow = using static methods for their `abstract static` classes access to = `@internal docblock` =E2=80=94 which I argued against elsewhere in this = thread =E2=80=94 and let Hyrum's Law take over, OR do we enable them to = disallow calling those `static` methods from the `abstract` class = itself?

More = importantly, IF we do not immediately disallow calling `static` methods = on `abstract static` classes then we will never be able to = disallow in the future, because of BC. But on the flip side we could = later open them up for calling if we found the limitation to be = problematic.

 or if it applies the change = everywhere it's going to be a BC = break.

And to be clear, I am against BC breaks in almost all cases. = So bringing that up between us is moot.

All that said, if you tell me "I don't care about closing the door on being able to disallow = developers from calling static methods on `abstract static` methods = because prior to `abstract static` classes `static` methods could be = called on `abstract` classes in the past" I will respect that, = and as I said above, it won't bother me.  

My only reason for persisting is to = ensure that the argument I was making was understood before it was = dismissed.

-Mike

[1]  Ignoring there were technical issues = with allowing untyped to be readonly, which could have been gotten = around somehow if the consensus was "They must be able to = untyped."

= --Apple-Mail=_7B1473CB-DB97-4F08-90FE-56340668A018--