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

Xiaodi Wu xiaodi.wu at gmail.com
Wed Jun 29 18:04:24 CDT 2016


On Wed, Jun 29, 2016 at 6:00 PM, Matthew Johnson <matthew at anandabits.com>
wrote:

>
> On Jun 29, 2016, at 5:44 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Wed, Jun 29, 2016 at 5:41 PM, Matthew Johnson <matthew at anandabits.com>
> wrote:
>
>>
>> On Jun 29, 2016, at 5:30 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> On Wed, Jun 29, 2016 at 5:25 PM, Matthew Johnson <matthew at anandabits.com>
>>  wrote:
>>
>>>
>>> On Jun 29, 2016, at 4:30 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>> On Wed, Jun 29, 2016 at 4:15 PM, Jordan Rose <jordan_rose at apple.com>
>>> wrote:
>>>
>>>>
>>>> On Jun 29, 2016, at 14:12, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>
>>>> On Wed, Jun 29, 2016 at 4:07 PM, Jordan Rose <jordan_rose at apple.com>
>>>> wrote:
>>>>
>>>>>
>>>>> On Jun 29, 2016, at 14:03, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>>
>>>>> On Wed, Jun 29, 2016 at 3:15 PM, Jordan Rose via swift-evolution <
>>>>> swift-evolution at swift.org> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> > On Jun 29, 2016, at 13:13, Jose Cheyo Jimenez <cheyo at masters3d.com>
>>>>>> wrote:
>>>>>> >
>>>>>> > I know this might be have been brought up before but
>>>>>> >
>>>>>> > why not just disallow the “private" keyword for top level types,
>>>>>> extensions etc.
>>>>>> >
>>>>>> > A fixit could change top level `private` to `fileprivate`.
>>>>>> >
>>>>>> > I think this is a little less confusing since effectively this is
>>>>>> what is happening in the background.
>>>>>>
>>>>>> That doesn’t fix anything for inner types, so it’s a lot less
>>>>>> important than the rest of the amendment.
>>>>>>
>>>>>> There actually is an answer to this, which is that the core team
>>>>>> expects 'private' to be the common keyword, and therefore it’s better if
>>>>>> you can use it at the top level and ignore ‘fileprivate’ altogether in most
>>>>>> programs.
>>>>>>
>>>>>
>>>>> On second thought, wouldn't all of this be inapplicable if `private`
>>>>> literally meant visibility *only* within the current declaration, and
>>>>> neither outside it nor inside any nested types, etc.?
>>>>>
>>>>>
>>>>> Yes, but that's not very useful:
>>>>>
>>>>> public struct Foo {
>>>>>   private var value: Int = 0
>>>>>   public func test() {
>>>>>     print(value) // error
>>>>>   }
>>>>> }
>>>>>
>>>>>
>>>>> I suppose you could say that nested *types* are different from nested
>>>>> *functions,* but then we start getting complexity in a different
>>>>> direction. And it still doesn't fix the default access within a private
>>>>> type.
>>>>>
>>>>
>>>> Let me offer a principled rule: if I write `private var foo`, then
>>>> `foo` is invisible at such places within the declaration where writing
>>>> `private var bar` at the same place would cause `bar` to be visible where
>>>> `foo` is not or vice versa.
>>>>
>>>>
>>>> I’m sorry, I don’t understand.
>>>>
>>>> Stepping back, though, this part of the proposal *was* discussed back
>>>> when it was first going through, and it was settled (after some
>>>> disagreement and discussion) that pure lexical scoping was the best choice.
>>>>
>>>
>>> I entirely misunderstood that part of the debate. I had thought the gist
>>> of the discussion was that SE-0025 itself was an explicit break from purely
>>> lexical scoping, that the proponents of pure lexical scoping were arguing
>>> against its adoption, and that its acceptance by the core team was a move
>>> away from purely lexical scoping.
>>>
>>> Let me see if I can rephrase the difficulty as I perceive it. I had
>>> thought that this was an equivalent formulation of the problem that you are
>>> addressing with the amendment. The interpretation of `private` as a purely
>>> lexical scope results in the scenario as follows:
>>>
>>> 1. I declare `private var foo`
>>> 2. There are places in code where `foo` is visible but where its access
>>> level cannot be uttered (e.g., within a nested type, `foo` is not private
>>> to that nested type, but it is more narrow in scope than fileprivate,
>>> internal, or public)
>>>
>>> Your proposal is to allow `fileprivate` to be used in place of the
>>> unutterable access level. This seems like a hack. The necessity for it
>>> would go away if we stipulated `private` to exclude all places in code
>>> where `foo` is visible but where its access level cannot be uttered.
>>>
>>>
>>> You have this wrong.  It is not that you declare `private var foo` and
>>> then in specific places it is visible but you can’t utter its access
>>> control.
>>>
>>> The problem is when you use `private` on any construct which introduces
>>> a scope that contains further declarations.  You cannot utter the default
>>> access control for the members of that scope.  Here are examples:
>>>
>>> private struct S {
>>>     var foo: Int
>>> }
>>> private class C {
>>>     var foo: Int
>>> }
>>> private enum E {
>>>     var foo: Int { return 42 }
>>> }
>>> private extension S {
>>>     func bar() {}
>>> }
>>>
>>> In all of these examples `foo` and `bar` are visible within the top
>>> level scope, but not outside the file.
>>>
>>
>> Sorry, yes, that is one problem. The related problem I was trying to
>> describe was this:
>>
>> ```
>> public struct A {
>>   private var foo: Int
>>   internal struct B {
>>     // I cannot utter the access control for `foo` here
>>     // and there is nothing I can declare here to be visible
>>     // exactly where `foo` is visible
>>   }
>> }
>> ```
>>
>>
>> Access control is never uttered at *usage* sites.  It is uttered at
>> *declaration* sites.  By definition of scope-base access control you are
>> not going to be able to utter the precise visibility level of some visible
>> declarations at the *usage* sites.  I don’t see why this is a problem.  It
>> is utterability at *declaration* sites that is important.
>>
>
> Sorry, I'm being sloppy here. Inside struct B, I intend to declare things.
> Substitute `typealias Foo` for `var foo` and declarations inside struct B
> will have trouble with `A.Foo` because of restrictions concerning minimum
> visibility.
>
>
> I don’t understand why you say this.  Considering the typealias example,
> you can use `Foo` in the signature of any member of `B` that is `private`
> and with Jordan’s amendment `fileprivate`.  You just can’t use it in
> members with `internal` or `public` visibility.
>
> This is no different from Swift 2 because in Swift 2 `Foo` would behave
> the same as `fileprivate` in Swift 3 which is less than `public` and
> `internal`.
>

You're right. This was a failed attempt at an example :)


>>
>>> In this case that happens to correspond to `fileprivate` which is
>>> probably why Jordan selected that keyword.  In cases where these are not
>>> top level declarations, but nested within a scope these will be visible
>>> within that scope, but not at the top level of the file.  In *no* case does
>>> the unutterable access level correspond to *internal* which is probably why
>>> Jordan did not suggest using that.
>>>
>>> -Matthew
>>>
>>>
>>>
>>>
>>>>
>>>> Jordan
>>>>
>>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160629/1d8edfe2/attachment.html>


More information about the swift-evolution mailing list