On Sun, Nov 13, 2022, at 2:08 PM, Larry Garfield wrote:
> Hi folks.  Ilija is nearly done with the implementation for asymmetric 
> visibility and flushing out edge cases, but we've run into one design 
> question we'd like feedback on.
>
> There's two design decisions we've made at this point, both of which we 
> think are logical and reasonable:
>
> 1. If specified, the set visibility must be tighter than the get 
> visibility.  So `protected protected(set)` and `protected public(set)` 
> are not permitted, for instance.
>
> 2. `readonly` is a "write once" flag that may be combined with 
> asymmetric visibility.  If no set visibility is specified, `readoly` 
> implies `private(set)`, but a different set visibility may also be 
> provided.
>
> These are both reasonable rules.  However, it creates a conflict.  
> Specifically, in the following cases:
>
> public public(set) readonly string $foo
>
> protected protected(set) readonly string $foo
>
> These would be the only way to have a non-private-set readonly 
> property.  While the first is in practice quite unlikely, the second 
> has valid use cases.  (In particular, a base class that provides 
> properties expected to be set by a child constructor, and then used by 
> a method in the parent class.)  However, it would not be allowed under 
> the rules above.  Working around it would require specifying `public 
> protected(set) readonly...`, which means exposing a property that 
> likely should not be exposed.
>
> That creates an odd situation where readonly and asymmetric visibility 
> may only be combined "sometimes."  That is not deesireable.  The only 
> way to combine them in their current form is to allow `protected 
> protected(set)` only if readonly is in use, which is excessively 
> complicated both to implement and to explain/document/use.
>
> We see two possible ways to resolve this conflict:
>
> 1. Relax the set-is-tighter restriction.  That would allow `protected 
> protected(set)` etc. on any property.  It wouldn't be particularly 
> useful unless readonly is being used, but it would be syntactically 
> legal and behave as you'd expect.  We could still disallow "set is more 
> permissive" combinations (eg, `private public(set)`), as those have no 
> apparent use case.
>
> 2. Disallow readonly and asymmetric visibility being combined, because 
> readonly already has a hard-coded implied asymmetric visibility.  This 
> option removes some potential use cases (they would most likely drop 
> the readonly), but has the upside that it's easier to re-allow at some 
> point in the future.
>
> 3. Some other brilliant idea we've not thought of.
>
>
> Both are viable approaches with pros and cons.  We're split on which 
> way to go with this, so we throw it out to the group for feedback.  
> Which approach would you favor, or do you have some other brilliant 
> idea to square this circle?

Addendum: Ilija and I were talking past each other a bit, it seems.  Allowing 
`protected protected(set) readonly` only in the context of readonly would be 
straightforward to implement.  It's potentially not the easiest to explain that 
exception, but implementation-wise it's fine.

So that gives another viable option to consider:

4. Allow get and set visibility to be both set explicitly to the same level, 
iff in the presence of readonly.  So `protected protected(set) string $foo` is 
not allowed, but `protected protected(set) readonly string $foo` is allowed.  
This gives the most options and the least pointless syntax, but at the cost of 
having an exception that needs to be documented/explained/understood.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to