Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125756 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 7FDF01A00BD for ; Sun, 6 Oct 2024 07:25:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1728199694; bh=/WzHsp+QioV6E6Y+gvY4dAVCsJFp4rjZXq/BprX76cs=; h=Subject:To:References:From:Cc:Date:In-Reply-To:From; b=QJumFJAOh/ycvMGbR/Asy2IYEwl+uX3m0jahujdK88iwC3f11tfw49cVcK00eAuqi /hRLcJxYZmCDnNQHlq/3FdZutKYwIUR2F+GohKMI1t2fCHU8sc+GyNmujLeoxXFRz1 WaLagjgJLGo+BYb9BCu8iBxRe4sciuN6Pe2y2xe7b4leO9XWxHnq5mLatceL/UZAWG fMsKhIUpwG1vHvM0L2eCLez9T5f7+ig7PH10pwUx0nOaZ1zzOeahGtDJj3OAGeXdV3 CbqzNay4zZpd7WFa4/u174A7ndI9i8JR5E6gTZKPEKkFxGMG9YWRfWimVxrRTHFuA6 453+axdRtU14g== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 3F6A2180041 for ; Sun, 6 Oct 2024 07:28: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=2.3 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING, HTML_MESSAGE,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_SOFTFAIL,STOX_BOUND_090909_B autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from butterfly.birch.relay.mailchannels.net (butterfly.birch.relay.mailchannels.net [23.83.209.27]) (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 ; Sun, 6 Oct 2024 07:28:12 +0000 (UTC) X-Sender-Id: a2hosting|x-authuser|juliette@adviesenzo.nl Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 0B5FDC418C for ; Sun, 6 Oct 2024 07:25:56 +0000 (UTC) Received: from nl1-ss105.a2hosting.com (trex-10.trex.outbound.svc.cluster.local [100.96.88.243]) (Authenticated sender: a2hosting) by relay.mailchannels.net (Postfix) with ESMTPA id E00B0C475B for ; Sun, 6 Oct 2024 07:25:54 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1728199555; a=rsa-sha256; cv=none; b=nI541yD3TphFCwawsFIeCZPL2pvjA9VKiOQPnk8HzM3PXBM6AcanSyvxdId137za0e6Y68 nBX8eFLG7QAskr8p/btuwaQGx0fTaIERV6I9gB/gZhaNY8Y+jQiE27GNmo/u4ZXBhOA4tD mhytbgmR8ijTZwHk37uYn6N1CnyMWnM9ZGP/DLMLcahzMHaH+b3k56K3oiYahDp9r790iz XeaFjPqCHDHMZtIdk+xNgo6k8iJKncKMY64mLXHlsnPeAgCURS1Z2uya4q/lxHdy7s63wo 4sZpi6fqgakpz9D7mMU0UjLHcGYMnUHXW3TIVO25BtKUXqxdqQw6wmds/LJT6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1728199555; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references:dkim-signature; bh=fuQh0iPNFJ6UsAsjennACOXD5N60yu8IuyjSMqBjXnM=; b=rFJpusbkV40S+v6uY+xZC8um6P0mlJ8Igo7bYnwW/HFV+c+5weDy6f7Iry6cqoSDuybLR5 68ooIH2QXD6FtYd9ctSDYTUIRK/WyoAJpv98lpUq2TbTXsket362wzJdHcvFHFIQmbj9MR R/33EUZLdpW3A/Yx9wCrbl4cBoWv1HeggMcQQ62Z6Elu4+vUikNdURe0Xu158Frb3ZNFjS bEhfvuUiGA3b9FWonjdAo++27aa2DrArNKsH554FbNgOrmL46MrFKCNZJB6oef5pz54u23 b4Z7cMuI9BQNKu08RgkArxtX06VHx9cGtMT7k8vATDwESxYsgk4ym7unA1/eDg== ARC-Authentication-Results: i=1; rspamd-5778c966d7-rh5xd; auth=pass smtp.auth=a2hosting smtp.mailfrom=php-internals_nospam@adviesenzo.nl X-Sender-Id: a2hosting|x-authuser|juliette@adviesenzo.nl X-MC-Relay: Neutral X-MailChannels-SenderId: a2hosting|x-authuser|juliette@adviesenzo.nl X-MailChannels-Auth-Id: a2hosting X-Bored-Harmony: 6778d1f61a8f33d4_1728199555598_2077319809 X-MC-Loop-Signature: 1728199555598:1380921691 X-MC-Ingress-Time: 1728199555598 Received: from nl1-ss105.a2hosting.com (nl1-ss105.a2hosting.com [85.187.142.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.96.88.243 (trex/7.0.2); Sun, 06 Oct 2024 07:25:55 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=adviesenzo.nl; s=default; h=Content-Type:In-Reply-To:MIME-Version:Date: Message-ID:Cc:From:References:To:Subject:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=fuQh0iPNFJ6UsAsjennACOXD5N60yu8IuyjSMqBjXnM=; b=SzyDP1Lf99OHO2Z/t/xuDNy8XB 0E5P0RGnlmD/4oQECRdEC/ptSvJp3Q4j/gzT/NDqgXRf4vedkPqXMJXo9qqEnIEotpO75spYEJAA0 NT/H5zTCLD0YPDTYWr1zdgwszaiKxA+XzxxMliIY90kZG7wCNeTL+2WMjsHjY6wMOLg8=; Received: from mailnull by nl1-ss105.a2hosting.com with spam-scanner (Exim 4.97.1) (envelope-from ) id 1sxLeL-0000000GVQp-0UhC for internals@lists.php.net; Sun, 06 Oct 2024 09:25:53 +0200 X-ImunifyEmail-Filter-Info: UkNWRF9WSUFfU01UUF9BVVRIIFRBR0dFRF9SQ1BUIFJDVkRf VExTX0F MTCBUT19ETl9TT01FIFZFUklMT0NLX0NCIE1JRF9SSFNfTUFUQ0hfRl JPTSBCQVlFU19IQU0gRlJPTV9FUV9FTlZGUk9NIFRPX01BVENIX0VOV lJDUFRfU09NRSBBUkNfTkEgRlJPTV9IQVNfRE4gUkNQVF9DT1VOVF9U SFJFRSBNSU1FX1RSQUNFIFJDVkRfQ09VTlRfT05FIEFTTiBfRFJVR1N fTU1fRElTQ09VTlQgTUlNRV9VTktOT1dO X-ImunifyEmail-Filter-Action: no action X-ImunifyEmail-Filter-Score: -3.10 X-ImunifyEmail-Filter-Version: 3.8.5/202409250822 Received: from [31.201.40.213] (port=52081 helo=[192.168.1.16]) by nl1-ss105.a2hosting.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.97.1) (envelope-from ) id 1sxLeK-0000000GVOe-3BX8; Sun, 06 Oct 2024 09:25:52 +0200 Subject: Re: [PHP-DEV] [RFC] [Discussion] Add get_declared_enums() function To: internals@lists.php.net References: <66FC7B9F.5070906@adviesenzo.nl> Cc: nicolas.grekas+php@gmail.com, Ayesh Karunaratne Message-ID: <67023B59.6020301@adviesenzo.nl> Date: Sun, 6 Oct 2024 09:25:13 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------040801060301090605020109" X-AuthUser: juliette@adviesenzo.nl From: php-internals_nospam@adviesenzo.nl (Juliette Reinders Folmer) This is a multi-part message in MIME format. --------------040801060301090605020109 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit On 4-10-2024 13:44, Nicolas Grekas wrote: Hi Nicolas, > # Introduction of the new function: get_declared_enums() > > About this proposal, I shared a one-liner in the previous thread that > shows listing only enums is trivial already. > IMHO we don't need this function since the engine already provides > everything one needs if they want to list enums. I won't object > either, I'm just "-0". The upside of a PHP native function would be one of performance. > # Deprecation of using class_exists() on enum names > > This is a big NO on my side. This will break perfectly fine code for > the sake of some high level ideas that matter less is practice than > ensuring stability of the PHP platform. A BC break has to be worth it > and this is clearly not the case to me. The canonical examples are > checks like `class_exists($c) || interface_exists($c, false) || > trait_exists($c, false)`. This is common code to check if a symbol > exists in current PHP. Yet, with your RFC, all such checks would > become broken immediately. Well, this statement made me curious to see just _how_ common this type of code is, so I've done a scan of the Packagist top 2000 projects [1]. The check you mention is used a total of 36 times in ~20 packages out of 2000 (includes some duplication, mostly within Symfony, which also contains the fast majority of the uses of the above mentioned combination). The full break down of the scan results [2] are as follows: Combination of the following function calls within a set of parentheses (typically: control structure condition): 4 out of 4: class_exists() + interface_exists() + trait_exists() + enum_exists() 3 3 out of 4: class_exists() + interface_exists() + trait_exists() 36 2 out of 4: class_exists() + interface_exists() 131 2 out of 4: class_exists() + trait_exists() 8 2 out of 4: class_exists() + enum_exists() 1 2 out of 4: interface_exists() + trait_exists() 1 Combination of the following function calls within the same function scope (not necessarily in the same statement, excluding the above): 4 out of 4: class_exists() + interface_exists() + trait_exists() + enum_exists() 2 3 out of 4: class_exists() + interface_exists() + trait_exists() 17 3 out of 4: class_exists() + interface_exists() + enum_exists() 3 2 out of 4: class_exists() + interface_exists() 32 2 out of 4: class_exists() + enum_exists() 4 2 out of 4: class_exists() + trait_exists() 2 Please note that not all of this code would need updating. > BTW, this makes me wonder if we could have a new symbol_exists() > function, that'd basically do the above checks in one go? Mixing this > idea with Claude's, the signature could be symbol_exists($class, > $filter = -1, $autoload = true), where $filter is a bitfield that'd > allow listing only classes, abstract classes, interfaces, enums, > traits at will? > > # Change of the return value of get_declared_classes() > > This proposal is problematic on two aspects: > > 1. The planned BC break feels needless to me. Its motivation is very > moot compared to its impact on the PHP community, which will be > forced to update perfectly fine code. > Again, let's look at the real world impact based on a scan of the Packagist top 2000. In the top 2000 packages, there are only 47 calls to the `get_declared_classes()` function. These calls are found in 29 packages. [1][3] And for the record, there are only 16 calls each to `get_declared_interfaces()` and `get_declared_traits()`. Also note that not all of this code would need updating, only that code which is also targeting enums. > 1. The BC break is planned without any ahead-of-change deprecation > notice (except doc of course). From a deprecation policy POV, we > reject this practice in the Symfony community. We don't do "hard > BC breaks", or "unannounced" ones: we mandate that any BC break is > first announced in the current major. This ensures the community > won't miss the notice, and won't discover the BC break when it's > very late and thus costly. There is always a way to follow that > policy, so I'd strongly recommend adopting this practice in PHP > itself, and in this RFC today. Here, this could be done by either > keeping the function as is in PHP 9, or just deprecating it (in > favor of get_declared_symbols()?) > I hear what you are saying and largely agree with you. The problem is, of course, that it seems unlikely that we can find a way to throw a deprecation for this, as PHP would then also throw a deprecation for code which needs no changes (which only _intends_ to look at classes, not enums). In the RFC, we mention an alternative approach [4], building upon the suggestion by Claude. This alternative approach would allow for deprecations to be thrown, but would, in my estimation, need a longer lead-time. Something like: introduce the new function in PHP 8.5, deprecate use of the old functions in PHP 9.last and remove in PHP 10.0. I can imagine combining the alternative approach via get_declared_symbols() with a new symbol_exists() function like you suggest above (with a similar slow path to deprecate and remove the old functions). On the plus side, the alternative approach makes for much more versatile functionality. In a number of the cases I looked at, the results from various get_declared_*() functions are combined before further processing, so having a `get-declared_symbols()` function would allow for simplifying that code. The same can be said for the *_exists() functions. On the downside, the alternative approach makes for a larger BC break (if combined with deprecation and eventual removal of the old functions). Would you consider that approach preferable ? > You've been a rightfully vocal criticizer of BC breaks / deprecations > in PHP. Please help the vast part of the community that favors > stability 🙏 I evaluate each RFC on their merit and weight the impact and the effort which would be needed to handle the deprecation (and always have). For short: do the benefits outweigh the costs ? There are plenty of deprecations I've stayed silent about as those (IMO) weren't particularly problematic or even if they were, the arguments to deprecate were particularly strong. Just saying this, as I want to make sure people aren't confusing "speaking up when I see a problematic change" (which I do) with "being against deprecations" (which I'm not). Smile, Juliette 1: Based on the latest published release of each package and providing the package contained source code and not just a PHAR file. Excluding vendor and test directories. May contain some duplicates. Total number of files scanned: 233,968. 2: Detailed results of the scan for combinations of the *_exists() functions: https://gist.github.com/jrfnl/5ac6cf10e4553a5e2174cf0f58d5e305 3: Detailed results of the scan for usage of the get_declared_*() functions: https://gist.github.com/jrfnl/ccb11e73d804cc5bb7fe25c6899c43d1 4: https://wiki.php.net/rfc/get_declared_enums#were_any_alternative_approaches_considered --------------040801060301090605020109 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit
On 4-10-2024 13:44, Nicolas Grekas wrote:

Hi Nicolas,
# Introduction of the new function: get_declared_enums()

About this proposal, I shared a one-liner in the previous thread that shows listing only enums is trivial already.
IMHO we don't need this function since the engine already provides everything one needs if they want to list enums. I won't object either, I'm just "-0".

The upside of a PHP native function would be one of performance.

# Deprecation of using class_exists() on enum names

This is a big NO on my side. This will break perfectly fine code for the sake of some high level ideas that matter less is practice than ensuring stability of the PHP platform. A BC break has to be worth it and this is clearly not the case to me. The canonical examples are checks like `class_exists($c) || interface_exists($c, false) || trait_exists($c, false)`. This is common code to check if a symbol exists in current PHP. Yet, with your RFC, all such checks would become broken immediately.

Well, this statement made me curious to see just _how_ common this type of code is, so I've done a scan of the Packagist top 2000 projects [1].

The check you mention is used a total of 36 times in ~20 packages out of 2000 (includes some duplication, mostly within Symfony, which also contains the fast majority of the uses of the above mentioned combination).

The full break down of the scan results [2] are as follows:

Combination of the following function calls within a set of parentheses (typically: control structure condition):
4 out of 4: class_exists() + interface_exists() + trait_exists() + enum_exists() 3
3 out of 4: class_exists() + interface_exists() + trait_exists()                36
2 out of 4: class_exists() + interface_exists()                                131
2 out of 4: class_exists() + trait_exists()                                      8
2 out of 4: class_exists() + enum_exists()                                       1
2 out of 4: interface_exists() + trait_exists()                                  1


Combination of the following function calls within the same function scope (not necessarily in the same statement, excluding the above):
4 out of 4: class_exists() + interface_exists() + trait_exists() + enum_exists() 2
3 out of 4: class_exists() + interface_exists() + trait_exists()                17
3 out of 4: class_exists() + interface_exists() + enum_exists()                  3
2 out of 4: class_exists() + interface_exists()                                 32
2 out of 4: class_exists() + enum_exists()                                       4
2 out of 4: class_exists() + trait_exists()                                      2


Please note that not all of this code would need updating.

BTW, this makes me wonder if we could have a new symbol_exists() function, that'd basically do the above checks in one go? Mixing this idea with Claude's, the signature could be symbol_exists($class, $filter = -1, $autoload = true), where $filter is a bitfield that'd allow listing only classes, abstract classes, interfaces, enums, traits at will?

# Change of the return value of get_declared_classes()

This proposal is problematic on two aspects:
  1. The planned BC break feels needless to me. Its motivation is very moot compared to its impact on the PHP community, which will be forced to update perfectly fine code.
Again, let's look at the real world impact based on a scan of the Packagist top 2000.

In the top 2000 packages, there are only 47 calls to the `get_declared_classes()` function. These calls are found in 29 packages. [1][3]
And for the record, there are only 16 calls each to `get_declared_interfaces()` and `get_declared_traits()`.

Also note that not all of this code would need updating, only that code which is also targeting enums.

  1. The BC break is planned without any ahead-of-change deprecation notice (except doc of course). From a deprecation policy POV, we reject this practice in the Symfony community. We don't do "hard BC breaks", or "unannounced" ones: we mandate that any BC break is first announced in the current major. This ensures the community won't miss the notice, and won't discover the BC break when it's very late and thus costly. There is always a way to follow that policy, so I'd strongly recommend adopting this practice in PHP itself, and in this RFC today. Here, this could be done by either keeping the function as is in PHP 9, or just deprecating it (in favor of get_declared_symbols()?)

I hear what you are saying and largely agree with you. The problem is, of course, that it seems unlikely that we can find a way to throw a deprecation for this, as PHP would then also throw a deprecation for code which needs no changes (which only _intends_ to look at classes, not enums).

In the RFC, we mention an alternative approach [4], building upon the suggestion by Claude. This alternative approach would allow for deprecations to be thrown, but would, in my estimation, need a longer lead-time. Something like: introduce the new function in PHP 8.5, deprecate use of the old functions in PHP 9.last and remove in PHP 10.0.

I can imagine combining the alternative approach via get_declared_symbols() with a new symbol_exists() function like you suggest above (with a similar slow path to deprecate and remove the old functions).

On the plus side, the alternative approach makes for much more versatile functionality. In a number of the cases I looked at, the results from various get_declared_*() functions are combined before further processing, so having a `get-declared_symbols()` function would allow for simplifying that code. The same can be said for the *_exists() functions.

On the downside, the alternative approach makes for a larger BC break (if combined with deprecation and eventual removal of the old functions).

Would you consider that approach preferable ?

You've been a rightfully vocal criticizer of BC breaks / deprecations in PHP. Please help the vast part of the community that favors stability 🙏

I evaluate each RFC on their merit and weight the impact and the effort which would be needed to handle the deprecation (and always have). For short: do the benefits outweigh the costs ?
There are plenty of deprecations I've stayed silent about as those (IMO) weren't particularly problematic or even if they were, the arguments to deprecate were particularly strong.
Just saying this, as I want to make sure people aren't confusing "speaking up when I see a problematic change" (which I do) with "being against deprecations" (which I'm not).

Smile,
Juliette

1: Based on the latest published release of each package and providing the package contained source code and not just a PHAR file. Excluding vendor and test directories. May contain some duplicates. Total number of files scanned: 233,968.
2: Detailed results of the scan for combinations of the *_exists() functions: https://gist.github.com/jrfnl/5ac6cf10e4553a5e2174cf0f58d5e305
3: Detailed results of the scan for usage of the get_declared_*() functions: https://gist.github.com/jrfnl/ccb11e73d804cc5bb7fe25c6899c43d1
4: https://wiki.php.net/rfc/get_declared_enums#were_any_alternative_approaches_considered

--------------040801060301090605020109--