Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128117 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 lists.php.net (Postfix) with ESMTPS id 146491A00BC for ; Fri, 18 Jul 2025 16:29:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1752856087; bh=fr2oh9jZDlU02zh6Ih3+ZAiYI8jHdB9mKPw9ewYzs5c=; h=Date:Subject:To:References:From:In-Reply-To:From; b=ZQJyunViVpgEnUZCSTv1v2WkAE+TM1htWFWbNWgEyFG/YdoMpJ39p4wB3c+Nh4QnE MKrYdXPfKBEMEGy5XNwLUFXbnNEHTC3p6iZGPZfQfZDGNghmXYDT81+VfEKQK0C+i6 gzXCERabqcYCNTHQXV8Wds8Il67U3lPYZby/A8SwVPk7gzqY/oXJgApMXqvxJLCTU6 uw31eLP9qhhr0e2/Ii/aXoZvz8a+zd+52Y0YxVJRzvMWIHa7tik1jLOlNjmTLDu/XP KtoQ7umSymRXx5iBFtJsmThbPiyWVW/jSRoCDgTUJsC4SHGi03vT5sF+jJFjdt1UoT YS9UBCZAeVEtg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 3AD261801D9 for ; Fri, 18 Jul 2025 16:28:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (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 ; Fri, 18 Jul 2025 16:28:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1752856189; bh=Xx1pYRgXQzClSw9VFdLDnzd2Z28ZfxlGtdG/yss1+k4=; h=Message-ID:Date:MIME-Version:Subject:To:References:From: In-Reply-To:Content-Type:from:to:cc:subject:message-id; b=Qo02FMCt60fYKdCWXtLqF2IW2CmZWHWAUzXQFH27WIhALgna1SYHDwlvOPLUzBYWj aphmDmzZ8fJzzz75YBve5s9IckmLlsg7yffvog+h0do5E8MeoCkE+ajCjoUiiR5Nxj CvfbfjEF6QvKP1syDLrVcCftaOhljSzQaoc463FJYgdryasFIlIRKkBj+TMqIJ2Y8h tghrxpj6ZbQCXNCcuqjUZzgGPHoH/+Fo/m7/I2gyhga6AiSy7XUC9eH6Y7arL6KVGQ TFkm6dTNZ5NGgaLZmMUujYlHtFuR3sQTtjVo8KKg+eScEYwcqIqOdD1kRFJ7Z6mPpc PacKg97bU6OSw== Message-ID: <0e8eb146-3b1d-4fc2-ad83-77062f2063c9@bastelstu.be> Date: Fri, 18 Jul 2025 18:29:48 +0200 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Subject: Re: [PHP-DEV] Re: [RFC] Readonly property hooks To: Larry Garfield , php internals References: <1e8634d7-ac1a-4025-b4e2-1948aabf5251@app.fastmail.com> <09780759-9ddc-45e2-9376-befb8e378775@app.fastmail.com> Content-Language: en-US In-Reply-To: <09780759-9ddc-45e2-9376-befb8e378775@app.fastmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi On 7/17/25 18:26, Larry Garfield wrote: > Given the lack of consensus both here and in off-list discussions on how to handle get hooks, we have done the following: > > * Split the RFC into two sections, one for get, one for set. > * Expanded and refined the examples for both. The implementation is still the original, however. > * Split the vote into two: one for allowing readonly get hooks, one for readonly set hooks. > > We will start the vote sometime this weekend, most likely, unless some major feedback appears before then, and let the chips fall where they may. After working through (most of) the discussion, I've now taken a look at the updated RFC. I have the following remarks: 1. > It is really “write-once”, which is not the same as immutable (as shown above). But there's no reason that “write-once” need be incompatible with hooks. This is a strawman argumentation, as I've outlined in my previous emails, calling readonly "write-once" is wrong. It is a reasonable user expectation to always get the identical value when reading a value that may only be set once. By calling it "write-once" you are trying to shift the focus to the write operation, which is totally irrelevant for user expectations when interacting with readonly properties. Especially for expectations of users that just *use* a class rather than writing one. 2. > The concern would only appear if someone is deliberately doing something non-stable Or if someone accidentally calls a (deep) function chain that is non-pure. 3. > Or, for a more real-world and larger example, PHP 8.4 requires this: This is false. You are perfectly able to write this in PHP 8.4: final readonly class Entry { public readonly $terms; public function __construct( public string $word, public string $slug, array $terms, ) { $this->terms = $this->upcastTerms($terms); } private function upcastTerms(array $terms): array { $upcast = static fn (Term|array $term): Term => $term instanceof Term ? $term : new Term(...$term); return array_map($upcast, $value) } } In no way do you need to use a property hook. 4. > // New code in 8.5: > > $p = new PositivePoint(3, 4); > $p2 = clone($p, ['x' => -10]); This is not legal code in PHP 8.5. Clone-with respects visibility and since your asymmetric visibility RFC included the change, you are probably aware that `readonly` implies `protected(set)`. 5. > but are now necessary to ensure that invariants are enforced. And therefore with PHP 8.5 hooks are not necessary to enforce invariants, except in the rare case where a `public(set) readonly` property is used. 6. > So no guarantees are softened by this RFC. Yes, they are. Unless `__get()` is implemented on a class (which is explicitly visible as part of the public API), readonly guarantees the immutability of identity. 7. > While that is an interesting idea that has been floated a few times, it has enough complexities and edge cases of its own to address that we feel it is out of scope. While it certainly is your right as the RFC authors to consider certain things out of scope for an RFC, I strongly oppose the notion of shipping something that is strictly inferior and comes with obvious semantic issues due to perceived complexity of another solution and then following up with the proper solution that has already been identified. As I've outlined in my previous emails, I found defining semantics for an 'init' hook straight-forward when looking at how PHP works as of today. 8. > However, this RFC is in no way incompatible with adding an init hook in the future should it be proposed. This is true, but as I've mentioned before, an 'init' hook would enable the same use cases without bringing along issues. So it really should be "one of them, but not both" (with "one of them" being the init hook). -------- After reading through the discussion, it seems the only argument against the 'init' hook is perceived complexity. It is not at all clear to me why this means that we must now rush something with clear issues into PHP 8.5. Best regards Tim Düsterhus