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

Reply via email to