Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125796 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 D393B1A00BD for ; Mon, 14 Oct 2024 03:22:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1728876288; bh=CsgIG1ojc6ZMxYC85mXUaF/uarpmihRz8+ovporUgqs=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=OjmLspj87O9faezm520xqRwRFo/9H1jxVxaa1TlITMyDuy0PSVoSoQNDTGayeZ9PJ uRdf67B5Te3YIMBvjplWBqVSSj8Q01udCnHt1z6t5LPlba+xtBxwcncy2jdlwc7rHK 6x6kD5+HxjxRjMKTG5uCj/p/pPAn8pSBt7/ykv34+rG05dkaQl016+O+ry7Fb3CjsK RPEL2YnaMs2gQ9UD2xb6XFG+5WQmA1C8/C5ZP/La7GJFKektaTxt5LuVaiT4rbHxym /Uydd//W6M2OtBv9RLUG709oUwMGq/Nvxf/ntk4ivFGZqZoPu9giKblB5DyDvHVBy4 gCdLdWdyPueXQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A3EC1180042 for ; Mon, 14 Oct 2024 03:24:47 +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.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (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 ; Mon, 14 Oct 2024 03:24:46 +0000 (UTC) Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-43117917eb9so33201195e9.0 for ; Sun, 13 Oct 2024 20:22:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728876145; x=1729480945; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=DwEKk/l72W9GVEZowTPxsLN2Bo50IVCfuy+JXS+na7Q=; b=Ckix1X8JYmZnF/4eu4cKFHD8p5NaoIxWQmcdwtcEw+Ff/v0+rb35oKOwJpc+0R29N+ w3Rwow9RBCW0vBCZztVo4Rb3UUP9gpgMtnrPm9mR5eGngBEohNl8vr4L38LV/SFWWSHy qPnDdt/BvdCt1FaH7DQu2F7bHQe0a61QGLQq2Ar2tB0hkD8useqBK8nJv4T0DG273mBW AAKb5cbgV0lPSBdPfP5Eoui4ycGRTx5vqk+HgAjLo3iAXzxk/x93SImCRre2aDYO6fPD /U/RQzJKV+7QlBo0AqhCKbOvGTHr850+RfvjZn0jXbQAlQtWHuOAa7RuZL2oKSAecUuv Dvww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728876145; x=1729480945; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DwEKk/l72W9GVEZowTPxsLN2Bo50IVCfuy+JXS+na7Q=; b=BzpSGna8aU17cTfPUoxT+++GKu/f9gAvoyhrrtYh5LkzXncI4eC9vhX2F//WXqq7CY /rg1jKGTgJ45JxCkchybLcqXNNw1Mgz9r9hU9z3VYOgBv4XDFFqUvTDNx0BpXiSRL0n9 gnX6Ppqs+ZYvfVkhEtq78hfqNC45qURtqD5lf1P56EUUULMylBXYpjJ/lMc8J6cTaWps fJpj5fslNEk0ppuzFuCPN4p1hovstC9LO7Mch6dWc9NeLzXZW2mm7DmtKAOwXWOuOD8I NMp8JJWk+RmPTpaMS30qHeYFHDUhJxTXhv9Q735qslRJ8o/JZeNkyHLpdSeQnYcNVoit Hi3A== X-Gm-Message-State: AOJu0YwGFx0VrfsMT9wq7f3gPo0/F9EwLJHTgppzh90URou7ugipbFTS W2opBBzbbhW1zNRyUvk7HfdtOZKKC2Gvbu/zQNNyVlW2t6VzpFkhxrQELsJi/w4FcfdGDjmMKWt L7MbEAqRIJJEAqxAqNXyoQjQzHPzmFlBsNQ== X-Google-Smtp-Source: AGHT+IEm61wGugNE6NX8yvzuvCLtuCXj66UzZy1d9weYmFgV04m94g/TVoRqrmD10zkotylnX8UOAfINM/ZN/I5eU/w= X-Received: by 2002:a05:600c:5022:b0:42c:b7f9:4bbd with SMTP id 5b1f17b1804b1-4311df1e519mr87643365e9.26.1728876145110; Sun, 13 Oct 2024 20:22:25 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <2A7CF24F-3AE3-4125-965F-C65431C42DFB@gmail.com> <30a41608-a1ea-40a9-8d2a-c53c508cd89f@jnvsor.net> In-Reply-To: Date: Mon, 14 Oct 2024 06:22:13 +0300 Message-ID: Subject: Re: [PHP-DEV] Asymmetric visibility is a BC break To: Larry Garfield Cc: php internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: udaltsov.valentin@gmail.com (Valentin Udaltsov) On Mon, 14/10/2024=E2=80=AFat 06:01, Larry Garfield wrote: > > On Sun, Oct 13, 2024, at 9:37 PM, Valentin Udaltsov wrote: > > > > First of all, I have already agreed above that PHP does not have a BC > > break here. Now we are discussing the potential problems in the PHP > > ecosystem and how they could be mitigated. > > Ilija and I have discussed this issue a bit. > > The first issue is that isPublic() technically means "does this property = have the public flag set," and nothing more. Prior to 8.1, that implicitly = also meant "can the property be read and written to from public scope," bec= ause of how properties worked. (And same for isProtected().) That implicit = assumption became invalid in 8.1 with readonly, which stealth introduced li= mited and not fully designed asymmetric visibility as well as properties th= at could not be set multiple times from any scope. Full aviz in 8.4 doesn't= change that. It just makes the previous assumption change more apparent. T= he fact that no one seems to have reported it as an issue until now suggest= s it's not a particularly widespread problem. In practice, if someone is u= sing reflection to determine the visibility of a property, they'll be writi= ng to it through reflection as well if at all. > > The best solution here is probably to just clarify the docs, which I will= do as part of the aviz docs that I have already been working on. cf: http= s://github.com/php/doc-en/pull/3828 > > The second issue is that the behavior of isProtectedSet() / isPrivateSet(= ) was not as clearly defined in the RFC as it should have been. That's on u= s for not being clearer, as we apologize for the oversight. > > Those methods follow the low level pattern of isPublic() , that is, they = just report of a given flag is set, not what the implications of that flag = in various contexts are. That is consistent with the rest of the reflection= API, so we feel that is best left as-is. > > That still means the "so can I read/write this property or not?" questio= n has no simple operation for it. Again: it never did, we just kinda sorta = had it indirectly and implicitly. For that we feel the best answer, as well= as least disruptive given we're in RCs, is dedicated methods as Ilija has = already described that take all property behavior and context into account.= (isReadable and isWriteable.) > > As a reminder, the concept is: > > $rProp->isReadable($obj); // Can this property on $obj be read from the c= alling scope? > $rProp->isReadable($obj, 'static'); // Same as previous. > $rProp->isReadable($obj, null); // Can this property on $obj be read from= global scope? > $rProp->isReadable($obj, Foo::class); // Can this property on $obj be rea= d from code inside class Foo? > > $rProp->isWriteable($obj); // Can this property on object $obj be written= from the calling scope? > $rProp->isWriteable($obj, 'static'); // Same as previous. > $rProp->isWriteable($obj, null); // Can this property on object $obj be w= ritten from global scope? > $rProp->isWriteable($obj, Foo::class); // Can this property on object $ob= j be written from code inside class Foo? > > cf: https://github.com/php/php-src/pull/16209 > > (The use of null to indicate global scope is borrowed from Closure::bind(= ), which does the same.) > > These methods do runtime analysis to see if a property should be readable= /writeable. Specifically: > > isReadable() > * Checks that the property is readable from the passed scope > * Checks that the property is initialized (i.e. not typed and never writt= en to) > * Checks that the property is not virtual or has a get hook > isWritable() > * Checks that the property is writable (respecting symmetric and asymmetr= ic properties) from the passed scope > * Checks that the property is not readonly, is not yet initialized, or is= reinitializable (__clone) > * Checks that the property is not virtual or has a set hook > > Of note, this does not absolutely guarantee that a read/write will succee= d. There's at least two exceptions: One, some PHP built-in classes have ef= fectively immutable properties but do not use `readonly` or `private(set)`.= Those would not be detected here, until and unless they are updated to us= e the now-available mechanisms. (See, eg: https://github.com/php/php-src/i= ssues/15309) The other is that a get or set hook may throw an exception un= der various circumstances. There is no way to evaluate that via reflection= , so it's a gap that will necessarily always be there. > > Whether those methods are OK to add in the RC phase or if they should be = left to early 8.5, and if they would need a formal RFC, is up to the RMs to= decide. RMs, what is your preference? > > --Larry Garfield Hi, Larry! Thank you very much for this response. I agree with every point. I have only one comment about the methods' signatures. They should not require an object, because properties can be static or the developer might want to check writable/readable without instantiating an object (in a code generator, for instance). Then it makes sense to make `$object` the 2nd parameter. This will also be consistent with Closure::bind(). isReadable(?string $scope =3D 'static', ?object $object =3D null): bool isWritable(?string $scope =3D 'static', ?object $object =3D null): bool --=20 Best regards, Valentin