On Sun, Nov 9, 2025, at 07:09, Alexandru Pătrănescu wrote: > Hi Rob > > On Sat, Nov 8, 2025, 14:46 Rob Landers <[email protected]> wrote: >> __ >> Hello Internals, >> >> I’d like to introduce an RFC for discussion: >> https://wiki.php.net/rfc/namespace_visibility which proposes a new >> visibility modifier: private(namespace). >> >> This idea has appeared several times in previous threads but never >> progressed to a formal proposal (from what I could find). My hope is that >> with defined semantics, examples, and implementation details, we can >> evaluate it properly and see whether there’s support for moving forward. >> Feedback is very welcome. >> >> > > Nice work on this. > > > I have one issue: > > *Visibility hierarchy: *public < protected < private(namespace) < private > >> > I think is not a correct view of the real problem space, as the protected and > private namespace scopes are separate sets that might have things in common > but can also be distinct. > > I think the correct way to model it, is to have two hierarchies: > public < protected < private > public < private(namespace) < private > > Otherwise you can have things like > `protected private(namespace)(set)` > that is unclear how it should be handled. > Can you clarify what is the right-now expected get and set allowance for > these cases: > - child classes in the same namespace > - child classes in another namespace > - non-child classes in the same namespace > > > My suggestion is to not allow mixing protected and private namespace for aviz. > > -- > Alex
Hi Alex, I think you’re right, treating this as a simple linear hierarchy is misleading. `Protected` and `private(namespace)` *are *based on different axes: - `protected` is inheritance-based - `private(namespace)` is namespace-based So, for `protected private(namespace)`: - child class in the same namespace: read + write - child class in a different namespace: read-only - non-child class in the same namespace: forbidden Formally, we can consider the caller sets: - C[public] - C[protected] (declaring class ∪ subclasses) - C[ns] (all code in the exact declaring namespace) - C[private] (declaring class only) We have two partial orders: - C[public] ⊇ C[protected] ⊇ C[private] - C[public] ⊇ C[ns] ⊇ C[private] In general, C[protected] and C[ns] are incomparable (neither is a subset of the other). For asymmetric properties, the `(set)` visibility must satisfy C[set] ⊇ C[base]. If C[set] and C[base] are incomparable or otherwise not a subset, it’s a compile-time error. That yields: - `public` with any `(set)` visibility: C[any] ⊆ C[public] - `protected` with `protected(set)` or `private(set)` only: C[private] ⊆ C[protected] - `private(namespace)` with `private(namespace)(set)` or `private(set)` only: C[private] ⊆ C[ns] - `private` with `private(set)` only: C[private] ⊆ C[private] - `protected` with `private(namespace)(set)`: incomparable - `private` with `private(namespace)(set)`: C[ns] ⊈ C[private] I’ll update the RFC to drop the linear hierarchy and update with the subset rule explicitly with some examples. — Rob
