> On Jun 15, 2016, at 2:19 PM, Robert Widmann <[email protected]> wrote:
> 
> We have diagnostics specifically to prohibit this case.  You cannot raise the 
> access level of members.
> 
> private struct Foo {
>     internal var x : String = ""
> }
> 
> warning: declaring an internal var for a private struct.
> 
> Hence, the highest allowable level of access for x is private and it becomes 
> invisible.
> 
> I would not like the compiler to synthesize this in my code, and if it did I 
> would like the proposal to say it will raise access levels of members as you 
> would like it to.

That diagnostic is a good thing.  I am not suggesting that you to disregard it.

What you are missing is that the meaning of `private` is scope-dependent.  The 
following example is perfectly valid:

private struct Foo {
    fileprivate var x : String = “”
}

`fileprivate` inside `Foo` specifies the same visibility as `private` at the 
top level, thus we are not “raising" the visibility of the member.  If no 
modifier is provided for `x` it receives the same visibility as its containing 
type (up to `internal`).

Consider another example:

struct Foo {
    private struct Bar {
        var x : String = “”
    }
}

In this example we *cannot* mark `x` as `fileprivate` because that *would* 
raise the visibility of `x` beyond that of `Bar`.  `Bar` is only visible inside 
`Foo`, not at file scope.  This means that `x` also has visibility throughout 
the lexical scope of `Foo`, but not outside of it.

-Matthew


> 
> ~Robert Widmann
> 
> 2016/06/15 12:14、Matthew Johnson <[email protected] 
> <mailto:[email protected]>> のメッセージ:
> 
>> 
>>> On Jun 15, 2016, at 2:04 PM, Robert Widmann <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> 
>>> 
>>> 2016/06/15 11:47、Matthew Johnson <[email protected] 
>>> <mailto:[email protected]>> のメッセージ:
>>> 
>>>> 
>>>>> On Jun 15, 2016, at 1:37 PM, Robert Widmann <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> The scope of the *declaration* is not the issue.  The scope of its 
>>>>> *members* is.
>>>> 
>>>> Let’s consider an example:
>>>> 
>>>> private struct Foo {
>>>>   var bar: Int
>>>> }
>>>> 
>>>> // elsewhere in the same file:
>>>> var foo = Foo(bar: 42)
>>>> foo.bar = 44
>>>> 
>>>> `Foo` is declared private.  Private for this declaration is at the file 
>>>> scope.  The `bar` member has no access modifier so it has the same 
>>>> visibility as the struct itself, which is file scope.  This will also be 
>>>> true of the implicitly synthesized memberwise initializer.  
>>> 
>>> No, it is also private.  It does not inherit its parent scope because, 
>>> following the letter of the proposal, that symbol will only be visible 
>>> within the current declaration.  We cannot arbitrarily break access control 
>>> rules because it is convenient in one special case. 
>>> 
>>>> 
>>>> This means that it is possible to initialize `foo` with a newly 
>>>> constructed instance of `Foo` and to modify the `bar` member anywhere else 
>>>> in the same file.
>>> 
>>> bar is not visible here.  If it were you could break access control rules.
>>> 
>>>> 
>>>> If `bar` was also declared `private` this would not be possible as its 
>>>> visibility would be restricted to the surrounding scope of the initial 
>>>> declaration of `Foo`.  This means `Foo` would need to provide an explicit 
>>>> initializer or factory method with `fileprivate` visibility in order to be 
>>>> usable.
>>> 
>>> bar is private.  Declarations within Foo cannot decide to raise that access 
>>> level to make themselves more visible.  If this should be the case, the 
>>> proposal must be amended as much.
>>> 
>>>> 
>>>> Members with no explicit access modifier should have the same *visibility* 
>>>> as their containing type (with a maximum implicit visibility of internal), 
>>>> not the same *modifier* as their containing type.  The only case where 
>>>> there is a distinction is the new `private` visibility.  Maybe that is 
>>>> what is causing the confusion?
>>> 
>>> That is not what the proposal says.  The proposal says it is invisible 
>>> outside the current decl, which is the containing structure here.
>> 
>> The access modifier is applied to `Foo`, not `bar`.  `Foo` is visible in the 
>> scope of the “current declaration” (this is badly worded - it should say 
>> current scope, which is the file).  Because `Foo` has a visibility lower 
>> than `internal` the default visibility of its members match the visibility 
>> of `Foo`, which again is the current scope: the file.  The detailed design 
>> section of the proposal is sparse, but it correctly uses the phrase "visible 
>> only within that lexical scope” rather than the less precise (in the case of 
>> top-level code) “current declaration”.
>> 
>> I didn’t write the proposal but I was very heavily involved in the 
>> discussions and IIRC I provided the original suggestion for introducing a 
>> scoped access modifier.
>> 
>> If my example was the following:
>> 
>> private struct Foo {
>>   private var bar: Int
>> }
>> 
>> Then what you are saying would be correct.  However, The example I showed 
>> did not provide an access modifier for `bar`.
>> 
>> You cannot just apply the same *access modifier* to members of the type that 
>> do not contain an access modifier.  You have to apply the same *visibility* 
>> (limited to internal).  When a type is marked as `private` in the lexical 
>> scope of the file, its unmodified members will be visible in the same 
>> lexical scope as the type itself (which is the file in the current example).
>> 
>> -Matthew
>> 
>>> 
>>>> 
>>>> Does this help?
>>>> 
>>>> -Matthew
>>>> 
>>>>> 
>>>>> ~Robert Widmann
>>>>> 
>>>>> 2016/06/15 11:36、Matthew Johnson <[email protected] 
>>>>> <mailto:[email protected]>> のメッセージ:
>>>>> 
>>>>>> The scope for a top-level declaration is the file itself.  This means 
>>>>>> that top-level declarations with `private` and `fileprivate` should have 
>>>>>> the same behavior.  They should not be uninstantiable or unusable.
>>>>>> 
>>>>>> -Matthew
>>>>>> 
>>>>>>> On Jun 15, 2016, at 1:31 PM, Robert Widmann via swift-evolution 
>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>> 
>>>>>>> While implementing SE-0025 (fileprivate), I noticed an interesting bug 
>>>>>>> in the proposal.  Under the implementation outlined there, any 
>>>>>>> top-level structure, class, or enum declared private cannot possibly be 
>>>>>>> instantiated and so cannot be used in any way.  Because of this, 
>>>>>>> private top-level declarations are more often than not blown away 
>>>>>>> entirely by the compiler for being unused.  It seems strange to me to 
>>>>>>> allow a key language feature to act solely as a hint to the optimizer 
>>>>>>> to reduce the size of your binary.  Perhaps the restrictions around 
>>>>>>> private needs to be relaxed or the line between fileprivate and private 
>>>>>>> needs to be investigated again by the community before inclusion in the 
>>>>>>> language.
>>>>>>> 
>>>>>>> Thoughts?
>>>>>>> 
>>>>>>> ~Robert Widmann
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to