Re: [RFC] [Discussion] Friends

From: Date: Mon, 11 May 2026 16:31:08 +0000
Subject: Re: [RFC] [Discussion] Friends
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-130831@lists.php.net to get a copy of this message
On Mon, May 11, 2026, at 10:33 AM, Rob Landers wrote: > On Mon, May 11, 2026, at 16:58, Daniel Scherzer wrote: >> Surprisingly I think adding an entirely new syntax would actually result in the fewest >> breaking changes when userland classes add friends, because there is no ambiguity. >> $u->id always refers to the id on >> whatever class $u happens to be, including applying any shadowing; >> if you want to be sure to access the base User::$id, use >> <$u as User>->id. >> >> Before I dive in and actually add that, what do people think? > > By the end of it, I basically arrived at a calculus that makes a sorta > sense. Visibility levels are sets of callers, partial-ordered by > inclusion. An override is admissible iff the child's caller set is a > superset of the parent's at the call site. P's caller set for > $x with > friend F is {P, F}; C's shadowing with > protected $x gives {C ∪ > descendants(C)}; incomparable, so the override violates LSP. > > Through that lens, we can look at your options you identified. > > Option 1 basically kills the entire feature. > > Option 3 breaks polymorphism. It throws away legitimate overrides. > > Option 4 is an escape hatch, not a solution. There's already RFCs for > "as" in-progress, so you'd step on some toes there. Heh, I think I have > even proposed "as" before and ... from experience, competing with > someone's in-progress RFC without discussion with them beforehand is a > great way to have people get mad at you on this list. > > Option 2 is probably the closest "right" answer. It prevents there from > being invalid caller sets and can provide meaningful error messages at > compile time: "name collides with friended private variable; must > friend with class F or change the name x". > > Another option to consider is not allowing private variables/methods to > be accessed by friends. Only protected variables/methods. This allows > inheritance to work as normal and guarantees overrides are compatible. > > — Rob Honestly, this seems like the easiest model to explain to people. A friend class has the same access as a child class, ie, it gets protected but not private access. That's a very simple rule to document and explain, and seems like it would side-step a number of issues. (We had a similar conversation for aviz, IIRC, which is how we ended up on private => final and readonly => protected(set) simplifying a lot of issues.) That said, I am still skeptical. This seems simple enough, but I worry that it's still attacking the general problem in too specific a way (compared to modules or similar). --Larry Garfield

« previous php.internals (#130831) next »