[swift-evolution] [Discussion] A Problem With SE-0025?

Xiaodi Wu xiaodi.wu at gmail.com
Wed Jun 29 11:59:56 CDT 2016

On Wed, Jun 29, 2016 at 11:31 AM, Jordan Rose <jordan_rose at apple.com> wrote:

> On Jun 29, 2016, at 08:49, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Tue, Jun 28, 2016 at 9:06 PM, Jordan Rose via swift-evolution <
> swift-evolution at swift.org> wrote:
>> On Jun 28, 2016, at 19:03, Matthew Judge <matthew.judge at gmail.com> wrote:
>> Comments inline.
>> On Jun 28, 2016, at 04:14, David Hart via swift-evolution <
>> swift-evolution at swift.org> wrote:
>> Hello everybody,
>> I tried using the access rules defined in SE-0025 in some code of mine to
>> see what effect it would have. I came out of the experiment more
>> disappointed than I thought. Here are several reasons:
>> 1) The new rules make `private` more prominent compared to `fileprivate`
>> (the latter has a somewhat worse name). But at the same time, the Swift
>> community has developed a style of coding where a type is defined through a
>> set of extensions. To hide members from other types, but have access to
>> them inside the type extensions, we have often used `private` and placed
>> the type and its extensions in the same file. Because `private` is scoped,
>> we are forced into using `fileprivate` pervasively (which is uglier), using
>> `internal` instead (which is less safe) or moving the extension code into
>> the type's scope (which is against the way Swift code is being written
>> today). All of these options look worse to be than before SE-0025.
>> If I understand SE-0025 (even with the amendment) you can still spell the
>> access modifier to types as 'private' and get the same characteristics as
>> the pre-SE-0025 meaning or private, so I'm not sure I understand the
>> concern here. However (continued below)
>> 2) The new amended rules look complicated to me. I think they have the
>> risk of being confusing in practice, but we’ll have to see.
>> I definitely agree that the amended rules look complicated. It seems to
>> me that the amended set of rules is favoring simplifying the implementation
>> over simplifying the mental model.
>> My impression of what SE-0025 decided was that 'private' meant private to
>> the enclosing scope. If the access modifying 'private' was applied to a
>> type at the file scope, then it was synonymous with fileprivate and the
>> default access of members of that type should be fileprivate.
>> If a inner type was declared private, than the default access of members
>> of that inner type should be private to the Outer type, not fileprivate.
>> There is currently no way of expressing this access explicitly, but it does
>> not seem like an especially useful thing to need to spell.
>> Said in code, my impression of SE-0025 is that
>> private class Outer { // exactly equivalent to fileprivate
>>     var myVar = 0 // default: fileprivate
>>     private class Inner { // private to Outer
>>         var hiddenVar = 0 // default: private to Outer
>>         private var reallyHiddenVar = 0 // default private to Inner
>>     }
>> }
>> This is definitely one of the considered alternatives. Both Brent and I
>> didn’t like the idea of an access level that you couldn’t actually spell,
>> and even if we got past that, we’d still need a way to refer to it in
>> documentation and diagnostics. I would count that as a larger change than
>> just allowing ‘fileprivate’ in places that previously would have been
>> called redundant.
> I'm late to the party here, but I share the feeling that perhaps the
> amendment introduces a complicated mental model. But a lightbulb went off
> reading the amendment, specifically this parenthetical statement:
> "(The members [defaulting to fileprivate inside a private type] still
> cannot be accessed outside the enclosing lexical scope because the type
> itself is still private, i.e. outside code will never encounter a value of
> that type.)"
> Given that this is the case, wouldn't the same problem be entirely
> obviated by the following change to the formal rules:
> The default level of access control within any type (public, internal,
> fileprivate, or private) is `internal`.
> In the case of fileprivate or private types, the `internal` members still
> cannot be accessed where the containing type cannot be accessed.
> That does seem simpler at first, but it doesn’t remove any of the later,
> more complicated rules about *minimum* access, and when you can use a
> less accessible type in a (formally but not in practice) more-accessible
> declaration.

Your second rule as written is straight-up ungrammatical, so I can't say if
it makes any sense or becomes any more or less complicated ("a member...may
have `private` type"--huh?).

The rule about minimum access is needlessly complicated: `private` can
never satisfy a protocol requirement or be used for a required initializer
because of the very fact that it is private. We needn't say that
`fileprivate` is the minimum access required since there's nothing about
`fileprivate` that makes it the minimum. Thought experiment: if another
access level were to be introduced between `private` and `fileprivate`,
that could become the minimum access required. However, no matter what, it
is inherent to the SE-0025 definition of `private` that it can never
satisfy a requirement.

The rule about members inside extensions with access modifiers is
consistent with existing rules and doesn't need to be called out. That
said, does a `private extension` make sense at all?

Once those are in place, it seems better to use fileprivate, as the next
> level up, so that we can still warn about mistaken uses of ‘internal’, and
> so that we don’t have to special-case code later on in the pipeline that
> uses visibility to optimize.

Mistaken explicit use of `internal` can still be warned on. In your
proposal, `fileprivate` inside `private` still leaves room for optimization
that would require special-casing, no? In my proposed formulation,
`internal` simply takes on the practical meaning of "as visible to the
module as can be given what it's contained in", which seems like a
principled take that could be optimized without regarding it as

> (Alternately, I don’t think that’s the part of the mental model people are
> having trouble with.)

Maybe it's just me, but that's the first part of the mental model that's
exploding my mind.

> Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160629/387c92e8/attachment.html>

More information about the swift-evolution mailing list