Re: RFC: Namespace-Scoped Visibility for Methods and Properties
| From: | Rob Landers | Date: | Mon, 10 Nov 2025 19:19:31 +0000 |
| Subject: | Re: RFC: Namespace-Scoped Visibility for Methods and Properties | ||
| References: | 1 2 3 4 5 6 7 8 9 10 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-129191@lists.php.net to get a copy of this message | ||
On Sun, Nov 9, 2025, at 22:32, Rob Landers wrote:
>
>
> On Sun, Nov 9, 2025, at 21:51, Tim Düsterhus wrote:
>> For this one I am however not sure if it ticks the “composes well”
>> checkbox - that greatly depends on the syntax choice and how modules
>> will look like if/when they eventually arrive.
>
> I understand the concern. Composability matters a lot, especially for features that touch
> visibility. My goal with this RFC is to take a boundary PHP already has (the lexical namespace) and
> make it enforceable without needing to answer the bigger "what’s a module/package?"
> question first.
>
> Right now, different people in the ecosystem use namespaces in different ways: some treat them
> as hierarchical, some as flat prefixes, some map them to directory trees, some don’t. Trying to
> define prefix rules, upward/downward access, or package-like confinement gets us right back into the
> same conversation we’ve been stuck on. That’s why this RFC deliberately picks the simplest rule
> PHP could enforce today: exact namespace equality.
>
> If a future RFC defines modules/packages, namespace-visibility can either:
> - fold into that boundary,
> - be superseded by it, or
> - be used inside it (e.g.
internal for modules, £É
> `ɓzRÀÈÀˆ§ÛN¨private(namespace) within module internals).
>
> Nothing in this RFC makes that harder.
>
>>
>> Your RFC appears to use the old template for the “RFC Impact” section
>> which doesn't yet include the “Ecosystem Impact” subsection, but
>> indicating that “significant OPcache changes” are required makes me
>> wonder about the cost-benefit ratio.
>
> Thanks! I’ll look at the new template and call out ecosystem impact (this was originally
> written back in April/May?). On the OPcache point: "significant" is probably overstating
> it. The change is limited to persisting one additional interned string on zend_op_array and
> refcounting it correctly. The cost is paid at compile time, not at call time, so runtime performance
> impact should be negligible. I’ll reword this to be more precise.
>
>>
>> > Aviz establishes visibility(operation) as the pattern
>> > for asymmetric visibility, where the keyword controls the caller set and parentheses restrict the
>> > operation (get/set). That’s why private(namespace)(set) follows
>> > the same rule: the base visibility is still "private", and the parentheses narrows who may
>> > call it.
>> >
>> > If we introduced a standalone keyword like internal or
>> > nsviz, we’d effectively be adding a new visibility class, not a
>> > refinement of private and would bring its own semantics, collision
>> > issues, and interactions with any future module work. This RFC aims to minimise surface area, which
>> > is why it treats namespace visibility as a refinement.
>>
>> As noted in my reply in the thread from Faizan, calling this a
>> refinement of private is not really accurate / doesn't
>> work in practice.
>
> Agreed. After the discussion with you, Alex, and Larray, I think it's clearer to describe
> private(namespace) as a distinct caller-set, not a subset of
> protected or private. I’ll update the RFC text to reflect that and disallow weird combinations (to
> be more clearly defined in the RFC).
>
>>
>> > If the community prefers prefix-based visibility or package-level visibility, that
>> > could be explored in a follow-up RFC. I’m not opposed to more expressive forms; I’m just not
>> > binding this RFC to a package model the language hasn’t defined yet.
>>
>> To do so, the syntax would need to account for that. I have not yet seen
>> a good proposal for that that doesn't end up as “symbol soup” that
>> doesn't really fit the existing language syntactically.
>
> My earliest version simply used namespace:
>
> class P {
> namespace function x() {}
> }
>
> It might make sense to return to that syntax if people don’t like the current syntax. I
> don’t have a strong attachment to the exact spelling, what matters is the semantics.
>
> — Rob
I’ve updated the RFC and the implementation with some significant clarifications and corrections:
• *Inheritance semantics now follow protected rather than private*
private(namespace) members are inherited and must follow normal signature-compatibility
rules.
Visibility is enforced based on the declaring namespace rather than the inheritance hierarchy.
• *Incompatible redeclarations are now clearly defined*
Transitions between protected and private(namespace) are disallowed in
either direction.
This avoids unsound cases where substitutability would be broken for callers in the declaring
namespace.
• *Asymmetric visibility rules clarified*
protected and private(namespace) operate on different axes (inheritance vs
namespace), so mixed AViz like
protected private(namespace)(set) is now a compile-time error.
• *Expanded examples and error messages*
The RFC now includes clearer examples of the invalid cases, inheritance rules, and AViz
combinations.
• *Syntax moved to an explicit open issue*
Because the semantics now line up with protected rather than private, the
spelling private(namespace) may not be ideal.
I’ve listed this in the “Open Issues” section and I'll include some previously considered
alternatives that preserve the semantics here:
• namespace function x() {}
• local function x() {}
• private:ns function x() {}
• protected:ns function x() {}
My personal preference is toward the simpler forms (namespace or local),
but I’d like to collect feedback before changing the RFC text.
Updated RFC:
https://wiki.php.net/rfc/namespace_visibility
<https://wiki.php.net/rfc/namespace_visibility?utm_source=chatgpt.com>
Implementation:
https://github.com/php/php-src/pull/20421
Thanks to everyone who pointed out the inheritance edge cases; those surfaced issues that needed to
be addressed. Further feedback is welcome.
— Rob