> 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