Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128375 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 7AA061A00BC for ; Sat, 2 Aug 2025 20:18:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1754165802; bh=hKEOril9ihDecfT/FcR4+BAyjbimdKJAHV7Dsazzojs=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=InG+a6igxkgu25nf8HA3eCS7H6Xo7/Fi9Lj1ljzKWeQ0OJysRWRdGHyaCFUCkJL9j 7TNZSG3YCsDfq5ZVsz6HsSGRMxAJKQtI+poSy0RC+6cOOJuIbfQXTq12L7S+wElLxn UGJzUtRobKva4n7Rc7//qwL01W2HXi43CvAsQDIosUI1X5er2dUhfUM+lG33f3O8qV QPwitukHqKLFuzQd7qkT9YbHl9TvGmHSKKGmOY4NDSnXGSBcIkskNdTh6TpYJQ0fd6 tMXArbJSRrvfQi8krit+2wpepNTfL2Vk32VRVayywF9JyPKaDIEGnEeFhmzQGMgKyS 3EABG4v54JXbA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id E8B79180079 for ; Sat, 2 Aug 2025 20:16:40 +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=-3.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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 mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (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 ; Sat, 2 Aug 2025 20:16:40 +0000 (UTC) Received: by mail-wr1-f48.google.com with SMTP id ffacd0b85a97d-3a6cd1a6fecso2789885f8f.3 for ; Sat, 02 Aug 2025 13:18:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1754165900; x=1754770700; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=hKEOril9ihDecfT/FcR4+BAyjbimdKJAHV7Dsazzojs=; b=Dxg3LSnZ5zaLy2TfCH57O2od1Wg40XHQ8+RIWN2gPDLT2IFOYvsgHCR20Ck831cLxB scrmhU13/8QXAanFIkUhCiXguPtSusFHWFwRLqNUJmN6C51bXbVwloqn4nZL8jgWhzCQ AuD3DsI392Sm+ro1KdMOjryjmaJRmyBHAe7/Gv3swT1BGtvzopIV3viPDig+zEsVHAec moCgSYnmHxZ6jCL9OuRgEpDrJ08S9DLLWiurzX+Ii0rhOIIf7sYnnb8hcKJCpKKPTdN4 /3LEzBu/fXZP9wNu5k4Q5uhUrKIaoAkkbvaLDu06ty40njx1TjDQc4a7aMlAHpBx4wl4 Zkgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754165900; x=1754770700; h=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=hKEOril9ihDecfT/FcR4+BAyjbimdKJAHV7Dsazzojs=; b=ucwIJZy6clOzZl1OUS9hcAob0dabiw3i034RD3QZPm2sPihaGQxLqLD95eint8GNA7 rA2P9okg6ooQNFr9nR+sw3kTBUM+DMgW1bbcRQIhUBUXCZ/dwXq86v3WWTUrCiBBFMSW bQ4itbWu75xosM8Jadn4yjydYPUj3PMC77Ft99Urrg5IPgyyZaDjUgVIn771wdIilhmZ yXvLcQ7SjZmKW7HJsXCRtlVlJJHC/e2eQVzQ/PNmUsiPi3bAAMOgbGY/LcFAr2z9P2/s pf1sC7yNv4ByWZeSq0a9cQI3z5Gbh3al/l3kqYvY2n8bBtl0YIX+TDrpCgvJXj/siOlp fqbQ== X-Forwarded-Encrypted: i=1; AJvYcCU4fdl1Y87X+Bs/N+FdZ2+xIUzfWk9F1r1s/xa66gQnXU8Fk8bfX+lBfDym/8eqU2CT1jrpccZguDs=@lists.php.net X-Gm-Message-State: AOJu0YxZzSJDtDbHHnO6gTIwSyPSNjAL3KVlHj9AzCeZZj9yrroWAA5T aLfg0KSNp6H8g4QNaJBey0Ao0XgSrePVfdWaklkEmD+RiinkHNng8ccvc0VgIuuq8Ef6dx8xkXl eqXUJQWdJcR7m3KCd3oH9g9wkulKtQw== X-Gm-Gg: ASbGnctYqVknmA81JP0SpgSuJvc9v0Yr6L9AG8PS+k7NvBO37iVt+7JKoJrbjrXi7k/ cDbFTbYSmEdx5Lj7d+9kMxv5g8nRdP8Q1YQuWpUC+aRM9YUnBHZJcFedPO4U1VcH3Hzh+3pNOIZ cv+ebhrFzrfUKHaGFPgVCosJ53gIQrEtYwweCq1/xRKr21IOFgZlwpL3WiXY3mSI9spZn3R+RFz sdm2A== X-Google-Smtp-Source: AGHT+IGBrJD1emsH1mYH1ZY+XNw5+MJByZsL7rWxWNS5zZY7Yjk5TDaEofECdfJmdtmBE/XNRBkxjZVasxMRNkWXls8= X-Received: by 2002:a05:6000:1786:b0:3b7:5dda:d57 with SMTP id ffacd0b85a97d-3b8d94c4e74mr2554430f8f.50.1754165899600; Sat, 02 Aug 2025 13:18:19 -0700 (PDT) Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <2d516e15-2fc7-4ac4-b9c2-7146ac01cfb1@app.fastmail.com> <8c60c0b8-8826-49a4-80ba-973ff833fff7@app.fastmail.com> <900d2936-6afd-4eed-b08a-1540d124273a@app.fastmail.com> In-Reply-To: <900d2936-6afd-4eed-b08a-1540d124273a@app.fastmail.com> Date: Sat, 2 Aug 2025 23:18:07 +0300 X-Gm-Features: Ac12FXyV4q0K2ALWmWs_mBpVzGVMZ1BNdXqS5EjmNX5hhWkteFGeFi7vBqfHQYU Message-ID: Subject: Re: [PHP-DEV] Protected inheritance hierarchies To: Rob Landers Cc: =?UTF-8?Q?Alexandru_P=C4=83tr=C4=83nescu?= , PHP internals Content-Type: multipart/alternative; boundary="00000000000052a683063b6793fb" From: udaltsov.valentin@gmail.com (Valentin Udaltsov) --00000000000052a683063b6793fb Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Sat, Aug 2, 2025, at 22:17, Rob Landers wrote: > On Sat, Aug 2, 2025, at 19:04, Alexandru P=C4=83tr=C4=83nescu wrote: > > > > On Sat, Aug 2, 2025, 17:10 Rob Landers wrote: > > > > > On Sat, Aug 2, 2025, at 16:04, Alexandru P=C4=83tr=C4=83nescu wrote: > > > > On Sat, Aug 2, 2025 at 12:10=E2=80=AFPM Rob Landers w= rote: > > > On Tue, Jul 29, 2025, at 20:11, Jonathan Vollebregt wrote: > > I came across this edge case today: > > https://3v4l.org/R3Q8D > > Both psalm and phpstan think this code is A-OK (Once you add the > requisite type hints) but it causes fatal errors way back to PHP 5.0.0 > > ...... > > > It's not an edge case, in C2, you redefine a protected variable with the > same name and shadowed the original $v. That $v is different than C's $v. > It's easiest to see this with static access: > https://3v4l.org/0SRWb#v8.4.10 > > However, I don't know of any way to unshadow a property from $this to > access the ancestor's value (other than using private access), but it > exists and takes up memory; just accessing it is the hard part. > > =E2=80=94 Rob > > > > Hi Rob, > > I'm pretty sure that there is no shadowing happening in the example. > When the child instance is created, there is just one slot for the > property, as the child one replaces the parent one. > So basically the child property overrides the parent property rather than > shadowing it. > > True shadowing (two slots) only occurs when the parent property is > declared private. > > It's just that when redefining, it stores the declaring class, and so > there is this sibling class access issue. > > I'm wondering now if the access shouldn't be relaxed, in case we have the > parent class that initially defined the property. > > Of course, we should focus on non-static properties, as static ones are > different things, and there is some shadowing there. > > -- > Alex > > > Hi Alex, > > I=E2=80=99m not sure what you mean? https://3v4l.org/WKILh#v8.4.10 > > There is clearly shadowing going on. > > > > Hi Rob, > > As I said, let's leave aside the static case, as the question from > Jonathan was not about that. > > Given the class P that defines a protected property with value 1, > and a class C that extends P and re-defines the protected property with > the value 2, > please show me an example where you could get from an instance of class C > the value 1 of the parent class property that you think it's shadowed. > Bonus point, if you manage that, you could also set it to something else, > and so have a hidden storage for any object of class C that is not really > visible normally. > > As far as I know, there is no way to achieve that, and the reason is > because at runtime the objects have a single slot for the protected > property; the child class property overrides the parent class property wh= en > redeclared, and does not shadow it. > But please prove me wrong. > > > Thanks, > Alex > > > I mentioned in my first reply, there is no way to get an instance-level > property unshadowed. It is there though (according to inheritance.c, if I= =E2=80=99m > reading it right, it is still accessible, just not from user-land). > > In any case, there are lots of interesting footguns with properties and > inheritance: Problem with abstract nested object =C2=B7 Issue #47 =C2=B7 = Crell/Serde > . > > Could it be considered a bug that my first example produces a fatal > error instead of trying to access the shadowed parent property that it > has access to and is typed to use? > > > Other languages (such as C#, Java, etc: > https://www.programiz.com/online-compiler/0ud6UO24mHOTU) don=E2=80=99t al= low you > to access protected properties/methods on sibling classes. This is becaus= e > "protected" is usually used in the context of inheritance; access is > usually restricted to "myself" or "children" and a sibling is neither of > those. If there is a bug, the bug is that you can access a sibling=E2=80= =99s > protected properties, at all. > > =E2=80=94 Rob > > If there is a bug, the bug is that you can access a sibling=E2=80=99s pro= tected properties, at all. In 2006 the absence of this feature was fixed as a bug and meged in PHP 5.2: https://bugs.php.net/bug.php?id=3D37632 In 2020 Nikita Popov agreed that this is expected: https://x.com/nikita_ppv/status/1261633126687805440 So one way is to explicitly mention this feature in the Visibility docs and fix the redeclaration issue to make things consistent. The other way is to deprecate sibling relations. --=20 Valentin --00000000000052a683063b6793fb Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Sat, Aug 2, 2025, at 22:17, Rob Lander= s <rob@bottled.codes> wrote:
On Sat, Aug 2, 2025, at 19:04, Alexandru P=C4=83tr=C4=83nescu wrote:<= /div>


On Sa= t, Aug 2, 2025, 17:10 Rob Landers <rob@bottled.codes> wrote:


On Sat, Aug 2, 2025, at 16:04, Alexandru P=C4=83tr=C4=83nescu w= rote:


On Sat, Aug 2, 2025 at 12:10=E2=80=AFPM Rob Landers = <rob@bottled.codes> wrote:
<= /u>
On Tue, Jul 29, 2025, at 20:11, Jonathan Vollebregt = wrote:
I came across this edge case= today:


Both psalm and phpstan think this code is A-OK (Once you add the=C2= =A0
requisite type hints) but it causes fatal errors way back to = PHP 5.0.0

...<snip>...

It's not an edge case, in C2, you redefine a protected= variable with the same name and shadowed the original $v. That $v is diffe= rent than C's $v. It's easiest to see this with static access:=C2= =A0https://3v4l.org/0SRWb#v8.4.10

However= , I don't know of any way to unshadow a property from $this to access t= he ancestor's value (other than using private access), but it exists an= d takes up memory; just accessing it is the hard part.

=
=E2=80=94 Rob


Hi Rob,

I'm pretty sure that = there is no shadowing happening in the example.
When the chi= ld instance is created, there is just one slot for the property, as the chi= ld one replaces the parent one.
So basically the child property o= verrides the parent property=20 rather than shadowing it.

True shadowing (tw= o slots) only occurs when the parent property is declared private.

It's just that when redefining, it stores the declarin= g class, and so there is this sibling class access issue.

I'm wondering now if the access shouldn't be relaxed, in ca= se we have the parent class that initially defined the property.
=
Of course, we should focus on non-static properties, as stat= ic ones are different things, and there is some shadowing there.
=
--=C2=A0
Alex
<= br>
Hi Alex,

I=E2=80=99m not sure what y= ou mean?=C2=A0https://3v4l.org/WKILh#v8.4.10

<= div>There is clearly shadowing going on.



Hi Rob,
=

As I said, let's leave as= ide the static case, as the question from Jonathan was not about that.

Given the class P that defin= es a protected property with value 1,
and a class C = that extends P and re-defines the protected property with the value 2,
please show me an example where you could get from an in= stance of class C the value 1 of the parent class property that you think i= t's shadowed.
Bonus point, if you manage that, y= ou could also set it to something else, and so have a hidden storage for an= y object of class C that is not really visible normally.

As far as I know, there is no way to achie= ve that, and the reason is because at runtime the objects have a single slo= t for the protected property; the child class property overrides the parent= class property when redeclared, and does not shadow it.
But please prove me wrong.


Thanks,
Alex


I me= ntioned in my first reply, there is no way to get an instance-level propert= y unshadowed. It is there though (according to inheritance.c, if I=E2=80=99= m reading it right, it is still accessible, just not from user-land).
=

In any case, there are lots of interesting footguns wit= h properties and inheritance:=C2=A0Problem with abstrac= t nested object =C2=B7 Issue #47 =C2=B7 Crell/Serde.=C2=A0
Could it be considered a bug that my= first example produces a fatal=C2=A0
error instead of trying to = access the shadowed parent property that it=C2=A0
has access to a= nd is typed to use?

Other languages (= such as C#, Java, etc:=C2=A0https://www.programiz.com/online-com= piler/0ud6UO24mHOTU) don=E2=80=99t allow you to access protected proper= ties/methods on sibling classes. This is because "protected" is u= sually used in the context of inheritance; access is usually restricted to = "myself" or "children" and a sibling is neither of thos= e. If there is a bug, the bug is that you can access a sibling=E2=80=99s pr= otected properties, at all.

=E2=80=94 Rob

>= ; If there is a bug, the bug is that you can access a sibling=E2=80=99s pro= tected properties, at all.

In 2006 the absence of this feature was f= ixed as a bug and meged in PHP 5.2:=C2=A0https://bugs.php.net/bug.php?id=3D37632
In = 2020 Nikita Popov agreed that this is expected:=C2=A0https://x.com/nikita_ppv/status/1= 261633126687805440

So one way is to explicitly mention this feat= ure in the Visibility docs and fix the redeclaration issue to=C2=A0make thi= ngs consistent.

The other way is to deprecate sibling relations.

--
Valentin
--00000000000052a683063b6793fb--