[swift-evolution] [swift-evolution-announce] [Review] SE-0159: Fix Private Access Levels

Xiaodi Wu xiaodi.wu at gmail.com
Tue Mar 21 22:15:08 CDT 2017


On Tue, Mar 21, 2017 at 9:40 PM, Charles Srstka <cocoadev at charlessoft.com>
wrote:

> On Mar 21, 2017, at 9:17 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>
> On Tue, Mar 21, 2017 at 8:31 PM, Charles Srstka <cocoadev at charlessoft.com>
>  wrote:
>
>>
>> On Mar 21, 2017, at 8:15 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> On Tue, Mar 21, 2017 at 8:00 PM, Charles Srstka <cocoadev at charlessoft.com
>> > wrote:
>>
>>> On Mar 21, 2017, at 7:49 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>
>>>
>>> On Tue, Mar 21, 2017 at 6:46 PM, Charles Srstka <cocoadev at charlessoft.c
>>> om> wrote:
>>>
>>>> On Mar 21, 2017, at 5:26 PM, Xiaodi Wu via swift-evolution <
>>>> swift-evolution at swift.org> wrote:
>>>>
>>>>
>>>> So, if four/five access modifiers are too many, which one is carrying
>>>> the least weight? Which one could be removed to simplify the scheme while
>>>> maintaining the most expressiveness? Which one doesn't fulfill even its own
>>>> stated goals? Well, one of the key goals of `private` was to allow members
>>>> to be encapsulated within an extension, hidden even from the type being
>>>> extended (and vice versa for members defined in the type). It says so in
>>>> the first sentence of SE-0025. As seen above in my discussion with Charles
>>>> Srstka, even supporters of `private` disagree with that motivation to begin
>>>> with. The kicker is, _it also doesn't work_. Try, for instance:
>>>>
>>>> ```
>>>> struct Foo {
>>>>   private var bar: Int { return 42 }
>>>> }
>>>>
>>>> extension Foo {
>>>>   private var bar: Int { return 43 }
>>>> }
>>>> ```
>>>>
>>>> The code above should compile and does not. If I understood correctly
>>>> the explanation from a core team member on this list, it's unclear if it
>>>> can be made to work without changing how mangling works, which I believe
>>>> impacts ABI and is not trivial at all. Thus, (a) even proponents of new
>>>> `private` disagree on one of two key goals stated for new `private`; (b)
>>>> that goal was never accomplished, and making it work is not trivial; (c) no
>>>> one even complained about it, suggesting that it was a low-yield goal in
>>>> the first place.
>>>>
>>>>
>>>> Multiple people have already brought up cases in which they are using
>>>> ‘private’. The repeated mention of another, unrelated use case that was
>>>> mentioned in the SE-0025 proposal does not invalidate the real-world use
>>>> cases which have been presented. In fact, it rather makes it appear as if
>>>> the motivation to remove ‘private’ is based on a strange invocation of the
>>>> appeal-to-authority fallacy, rather than an actual improvement to the
>>>> language.
>>>>
>>>
>>> I'm not sure how to respond to this. SE-0025, as designed, is not fully
>>> implemented. And as I said above, IIUC, it cannot be fully implemented
>>> without ripping out a lot of mangling code that is unlikely to be ripped
>>> out before Swift 4. _And there is no evidence that anyone cares about this
>>> flaw; in fact, you are saying as much, that you do not care at all!_ If
>>> this is not sufficient indication that the design of SE-0025 does not fit
>>> with the overall direction of Swift, what would be?
>>>
>>>
>>> Because there are other uses cases for ‘private', *not* involving
>>> extensions, which I *do* care about. The fact that part of the proposal was
>>> badly written (and really, that’s all this is
>>>
>>
>> Huh? The code above *should compile*--that is a primary aim for SE-0025.
>> It does not compile and there is not a timeline (afaict) for its compiling.
>> It does not bother you that the 25th proposal considered in the Swift
>> evolution process, already once revised, is not fully implemented and may
>> never be?
>>
>>
>> Someone finding a bug/oversight in the compiler behavior does not compel
>> me to throw out the baby with the bathwater, no.
>>
>
> You're not hearing the argument. No one "accidentally" included this
> design as part of SE-0025; it's sentence number one.
>
>
> Or not. Here’s the actual text of the introductory paragraph:
>
> "Scoped access level allows hiding implementation details of a class or a
> class extension at the class/extension level, instead of a file. It is a
> concise expression of the intent that a particular part of a class or
> extension definition is there only to implement a public API for other
> classes or extensions and must not be used directly anywhere outside of the
> scope of the class or the extension.”
>
> So here we have “class or extension”, or some variant thereof, five
> separate times. It honestly reads like it originally just said “class”, and
> the author systematically went through it and added “or extension” to each
> of them to make sure his/her bases were covered.
>

The meaning of that sentence is made quite clear by the example in code
given in that proposal:

```

class A {
   private var counter = 0

   // public API that hides the internal state   func incrementCount()
{ ++counter }

   // hidden API, not visible outside of this lexical scope   private
func advanceCount(dx: Int) { counter += dx }

   // incrementTwice() is not visible here}
extension A {
   // counter is not visible here   // advanceCount() is not visible here
   // may be useful only to implement some other methods of the
extension   // hidden from anywhere else, so incrementTwice() doesn’t
show up in    // code completion outside of this extension   private
func incrementTwice() {
      incrementCount()
      incrementCount()
   }
}

```

If `counter` is not visible in `extension A { ... }`, then I must be able
to define my own `counter` in extension A. That is just how visibility
works in Swift; no other understanding of "visibility" can be admitted
here. Unless you mean to argue that, in reading this proposal, you honestly
think it's correct that `counter` may or may not be declared in `extension
A { ... }` depending on where `class A` is declared.


> And didn’t quite succeed; the wording doesn’t account for value types.
>
> And anyway, I’m not sure how you even get “extensions should be able to
> shadow private members” as Priority Number One™, based on that sentence.
> Which part of the sentence does your code example violate? The sentence
> says that implementation details are hidden, and so they are. The struct
> can’t access the extension’s private members, or vice versa. The
> name-mangling issue that causes the compiler to choke is simply a *bug*, an
> unintended consequence that the author didn’t consider. And as I said
> before, I’d be perfectly fine with striking all the “or extension”s from
> that paragraph and having ‘private’ only restrict things inside the types
> themselves (within a module, of course).
>

Whether you're fine with that is neither here nor there. It was not the
proposal reviewed and approved by the community, and it's not the proposal
considered here.


> Or, just fixing the mangling so that works. Honestly, I don’t understand
> what kind of point the above is supposed to make, other than pointing
> fingers and laughing at somebody for making a mistake.
>

The point I'm making is that `private` is *very* hard to reason about and
likely even harder to implement. This is not the mistake of the author or
the implementor of the proposal. The entire Swift community reviewed the
document not once but twice, and we are still discovering pitfalls. This
certainly backs up testimony that it is a difficult feature to learn and
teach. Does such a difficult feature hold its own weight? The argument made
in this proposal is that it overwhelmingly does not, and therefore the
complexity it adds to Swift is harmful.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170321/04a99414/attachment.html>


More information about the swift-evolution mailing list