Re: RFC: Namespace-Scoped Visibility for Methods and Properties

From: Date: Sun, 09 Nov 2025 20:31:27 +0000
Subject: Re: RFC: Namespace-Scoped Visibility for Methods and Properties
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-129182@lists.php.net to get a copy of this message
On Sun, Nov 9, 2025, at 20:55, Tim Düsterhus wrote: > Hi > > On 11/9/25 20:41, Rob Landers wrote: > > class P { > > private(namespace) function x() {} > > } > > > > class C extends P { > > protected function x() {} > > } > > > > This behaves the same as overriding a private method with a protected/public one today: > > the parent’s method is private to its declaring class, so the second example is allowed. > > This is unsound. As we have established, neither > private(namespace) > nor protected is a subset of each other. > > Specifically allowing this breaks the following (everything is declared > in the same namespace): > > class P { > private(namespace) function x() { } > } > class C extends P { > protected function x() { } > } > > function f(P $p) { > $p->x(); // legal, because f is in the same namespace as P. > } > > f(new C()); // breaks, because C::x() is protected and thus not > legal to access from f / the global scope. > > Best regards > Tim Düsterhus Initially, I treated private(namespace) like private for cross-namespace inheritance and overlooked how dynamic dispatch actually works in PHP. This means that a same-named method in a child would simply be a new method. But like you point out, that leads to a subtle problem. Even though P::x() is a method that’s visible and intended for callers inside namespace A, the runtime dispatch would pick C::x(). That completely and utterly destroys substitutability for namespace internal callers, which is exactly what this visibility is meant to protect. So ... it seems we need a couple of additional rules here: 1. If a parent has a private(namespace) method, then a subclass in a different namespace simply cannot declare a method with the exact same name. It’d be a compile time error to prevent shadowing and keep dispatch predictable. I’d also be open to other ways as well (such as always calling the namespaced method in the parent), but I’d need to see if that’s even possible in the engine. 2. As you pointed out, protected and private(namespace) aren’t compatible; thus we should only allow the same or a superset. So, it should only allow public or private(namespace) when inheriting in the same namespace. — Rob

« previous php.internals (#129182) next »