On Sun, Nov 9, 2025, at 07:09, Alexandru Pătrănescu wrote:
> Hi Rob
>
> On Sat, Nov 8, 2025, 14:46 Rob Landers <rob@bottled.codes> 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