SE-0025: Scoped Access Level, next steps


(James F) #1

I agree with the proposal of ‘inherited’ & ‘declaration’ modifiers.

Current access modifiers actually guarantee access. Limiting access using scope means another file/module can just add a property/function to make the value public. Confusing type-based and file-based access is a step backwards, and any attempt to add type-based access shouldn't be a breaking change.

Replacing internal with private(module) also seems like a step backwards, to me, and in my opinion changes to the ‘internal’ keyword should be part of a separate proposal.

Inherited & declaration modifiers compose well with existing access-modifiers, are clear in their purpose, can be applied to all access levels, and don't break existing code.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CAPUwzK7YHzwDMTMuH1Qvbojz3+9+ikgJvna3xDhscESVO8YSNQ@mail.gmail.com>

It's occurring to me, reading these recent posts, that we have two
orthogonal systems of access levels.

Swift's current access system is file based; a project file decides which
files comprise a module, and the terms 'public', 'internal' and 'private'
determine whether a property is accessible to all, accessible only within
files of the module, or accessible only within a file. (This takes on an
extra dimension as files may belong to several modules).

The concept which began this discussion, and several of the proposed
concepts in this discussion, ask instead for a type-based access system
similar to those in other languages including Objective-C, where 'public',
'protected' and 'private' are the terms of choice and they restrict access
to a type or subtypes.

I think it would be confusing if Swift applied 'public' to a concept in the
file-based access system and 'private' to a concept in the type-based
access system.

I would prefer clearer terms which actually mention the restrictions of the
level. For example, 'inherited', not 'protected', in the case of properties
accessible by a class and its subclasses; 'declaration', rather than
'private' or 'scoped', to refer to properties only accessible within a
given type or extension declaration.

Since, at the moment, a declaration can only occur within one file, I think
this most-restricted level has managed to pass as a level of the file-based
access system. However, if the system is ever extended, we're going to run
into new syntax decisions where we have 'private module' functions
(accessible only within the given type in the same module) trying to
communicate with 'protected file' properties (accessible only with the type
and its subtypes in the same file), and that might lead to conflicts, so
perhaps we should decide how those might be declared now.

···

On Tue, Mar 15, 2016 at 11:51 PM, Jonathan Hull via swift-evolution < swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

On Tue, Mar 15, 2016 at 2:33 PM Erica Sadun <erica at ericasadun.com <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:

And again, moving the access control modification to the end just doesn't look
right to me or seem to enhance readability. :frowning:

I like Shawn’s proposal better for cases where there are custom
getter/setter implementations. We should definitely be able to do:

var foo:Int {
public get {…}
private(file) set {…}
}

In fact, that is what I first tried to do before learning about
private(set). But without the implementations, it just seems strange to
put the scoping after the rest of the declaration (they work above because
they are *before* the custom getter/setter).

I still like the idea of having the option to use parameter-like syntax
for cases where you don’t have custom getters/setters:

private var foo:Int
private(file) var foo:Int
private(set: file) var foo:Int
private(get: global, set: file) var foo:Int

I guess, if we had some way to represent the standard getter/setter, that
might work too. I don’t love it, but maybe with better wording?

var foo:Int{
public get useDefault
private(file) set {…}
}

Thanks,
Jon

On Mar 14, 2016, at 10:22 PM, Patrick Pijnappel < >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

I like Shawn's proposal:

var foo: Int { private(file) set }

In fact it's probably more sensible than the current private(set) IMO.

For example, we already use

var foo: Int { mutating get { ... } }

and not

mutating(get) var foo: Int { get { ... } }

On Tue, Mar 15, 2016 at 4:13 PM, Patrick Pijnappel < >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

I like Shawn's proposal:

var foo: Int { private(file) set }

In fact it's probably more sensible than the current private(set) IMO.

While I like private(get: file, set: module) idea, I think it just gets
too inconsistent with private(set: public) and private(set: private) (?!)

On Tue, Mar 15, 2016 at 3:39 PM, Jonathan Hull via swift-evolution < >>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

*On Mar 14, 2016, at 8:36 PM, Patrick Pijnappel via swift-evolution <swift-evolution at swift.org <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:*

The only question is (as Sean mentioned) how this combines with the syntax
for setter access level, e.g. the current private(set). Options:
- Unnamed 2nd argument, giving private(file), private(file, set),
private(set).
- Named 2nd argument, giving e.g. private(file), private(file, accessor:
set), private(accessor: set). Less ambiguity but longer.
- Not using multiple arguments, but that'd probably break consistency with
the other unification efforts going on to make everything look like
function calls.

What about the following 3 forms?

private(file) //both setter and getter have file scope
private(set: file) //setter has file scope. Equivalent to current
“private(set)"
private(get: module, set: file) //getter has module scope & setter has
file scope

It is a bit weird, but we should probably also allow “public" in that
last form: private(get: public, set: module)

Thanks,
Jon

_______________________________________________
swift-evolution mailing list
swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
https://lists.swift.org/mailman/listinfo/swift-evolution

------------- End Message -------------

From James F


(Ilya Belenkiy) #2

Type based access would be confusing, which is why the proposal was for
scoped based access. This means that something is visible only in the scope
in which it is defined and is completely sealed from outside of the scope.
This way you have to modify the scope to make something more visible, so
you can't just add another extension to make something more visible.

Limiting access using scope means another file/module can just add a

property/function to make the value public. Confusing type-based and
file-based access is a step backwards, and any attempt to add type-based
access shouldn't be a breaking change.

···

On Wed, Mar 16, 2016 at 6:52 AM James Froggatt via swift-evolution < swift-evolution@swift.org> wrote:

I agree with the proposal of ‘inherited’ & ‘declaration’ modifiers.

Current access modifiers actually guarantee access. Limiting access using
scope means another file/module can just add a property/function to make
the value public. Confusing type-based and file-based access is a step
backwards, and any attempt to add type-based access shouldn't be a breaking
change.

Replacing internal with private(module) also seems like a step backwards,
to me, and in my opinion changes to the ‘internal’ keyword should be part
of a separate proposal.

Inherited & declaration modifiers compose well with existing
access-modifiers, are clear in their purpose, can be applied to all access
levels, and don't break existing code.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CAPUwzK7YHzwDMTMuH1Qvbojz3+9+ikgJvna3xDhscESVO8YSNQ@mail.gmail.com
>

It's occurring to me, reading these recent posts, that we have two
orthogonal systems of access levels.

Swift's current access system is file based; a project file decides which
files comprise a module, and the terms 'public', 'internal' and 'private'
determine whether a property is accessible to all, accessible only within
files of the module, or accessible only within a file. (This takes on an
extra dimension as files may belong to several modules).

The concept which began this discussion, and several of the proposed
concepts in this discussion, ask instead for a type-based access system
similar to those in other languages including Objective-C, where 'public',
'protected' and 'private' are the terms of choice and they restrict access
to a type or subtypes.

I think it would be confusing if Swift applied 'public' to a concept in the
file-based access system and 'private' to a concept in the type-based
access system.

I would prefer clearer terms which actually mention the restrictions of the
level. For example, 'inherited', not 'protected', in the case of properties
accessible by a class and its subclasses; 'declaration', rather than
'private' or 'scoped', to refer to properties only accessible within a
given type or extension declaration.

Since, at the moment, a declaration can only occur within one file, I think
this most-restricted level has managed to pass as a level of the file-based
access system. However, if the system is ever extended, we're going to run
into new syntax decisions where we have 'private module' functions
(accessible only within the given type in the same module) trying to
communicate with 'protected file' properties (accessible only with the type
and its subtypes in the same file), and that might lead to conflicts, so
perhaps we should decide how those might be declared now.

On Tue, Mar 15, 2016 at 11:51 PM, Jonathan Hull via swift-evolution < > swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

>On Tue, Mar 15, 2016 at 2:33 PM Erica Sadun <erica at ericasadun.com < > https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:
>
>And again, moving the access control modification to the end just doesn't
look
>right to me or seem to enhance readability. :frowning:
>
>I like Shawn’s proposal better for cases where there are custom
>getter/setter implementations. We should definitely be able to do:
>
>var foo:Int {
>public get {…}
>private(file) set {…}
>}
>
>In fact, that is what I first tried to do before learning about
>private(set). But without the implementations, it just seems strange to
>put the scoping after the rest of the declaration (they work above because
>they are *before* the custom getter/setter).
>
>I still like the idea of having the option to use parameter-like syntax
>for cases where you don’t have custom getters/setters:
>
>private var foo:Int
>private(file) var foo:Int
>private(set: file) var foo:Int
>private(get: global, set: file) var foo:Int
>
>
>I guess, if we had some way to represent the standard getter/setter, that
>might work too. I don’t love it, but maybe with better wording?
>
>var foo:Int{
>public get useDefault
>private(file) set {…}
>}
>
>Thanks,
>Jon
>
>
>On Mar 14, 2016, at 10:22 PM, Patrick Pijnappel < > >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>I like Shawn's proposal:
>
>
>
>var foo: Int { private(file) set }
>
>
>>In fact it's probably more sensible than the current private(set) IMO.
>
>
>For example, we already use
>
>var foo: Int { mutating get { ... } }
>
>and not
>
>mutating(get) var foo: Int { get { ... } }
>
>On Tue, Mar 15, 2016 at 4:13 PM, Patrick Pijnappel < > >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>>I like Shawn's proposal:
>>
>>var foo: Int { private(file) set }
>>
>>In fact it's probably more sensible than the current private(set) IMO.
>>
>>
>>While I like private(get: file, set: module) idea, I think it just gets
>>too inconsistent with private(set: public) and private(set: private) (?!)
>>
>>On Tue, Mar 15, 2016 at 3:39 PM, Jonathan Hull via swift-evolution < > >>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:
>>
>>>*On Mar 14, 2016, at 8:36 PM, Patrick Pijnappel via swift-evolution
<swift-evolution at swift.org <
https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:*
>>>
>>>The only question is (as Sean mentioned) how this combines with the
syntax
>>>for setter access level, e.g. the current private(set). Options:
>>>- Unnamed 2nd argument, giving private(file), private(file, set),
>>>private(set).
>>>- Named 2nd argument, giving e.g. private(file), private(file, accessor:
>>>set), private(accessor: set). Less ambiguity but longer.
>>>- Not using multiple arguments, but that'd probably break consistency
with
>>>the other unification efforts going on to make everything look like
>>>function calls.
>>>
>>>What about the following 3 forms?
>>>
>>>private(file) //both setter and getter have file scope
>>>private(set: file) //setter has file scope. Equivalent to current
>>>“private(set)"
>>>private(get: module, set: file) //getter has module scope & setter has
>>>file scope
>>>
>>>It is a bit weird, but we should probably also allow “public" in that
>>>last form: private(get: public, set: module)
>>>
>>>Thanks,
>>>Jon
>>>
>>>_______________________________________________
>>>swift-evolution mailing list
>>>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
>>>https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>
>
>
>_______________________________________________
>swift-evolution mailing list
>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
>https://lists.swift.org/mailman/listinfo/swift-evolution
>
>

------------- End Message -------------

From James F
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(James F) #3

Thanks for the clarification, I think this is the context I was missing. So this is a completely different type of access level, to either type-based or file-based? I'm still against making breaking changes, but I now understand why so many are supporting changing private.

Rereading the message I quoted (I now realise how badly I misinterpreted it), I think it does present a good case for keeping this scope-based keyword a separate keyword from the current ones. Type-based access would be a good feature to include eventually, as an indication of a variable/function's intended use more than anything (such as internal variables meant to be used in extensions).

From James F

···

On 16 Mar 2016, at 11:11, Ilya Belenkiy <ilya.belenkiy@gmail.com> wrote:

Type based access would be confusing, which is why the proposal was for scoped based access. This means that something is visible only in the scope in which it is defined and is completely sealed from outside of the scope. This way you have to modify the scope to make something more visible, so you can't just add another extension to make something more visible.

> Limiting access using scope means another file/module can just add a property/function to make the value public. Confusing type-based and file-based access is a step backwards, and any attempt to add type-based access shouldn't be a breaking change.

On Wed, Mar 16, 2016 at 6:52 AM James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:
I agree with the proposal of ‘inherited’ & ‘declaration’ modifiers.

Current access modifiers actually guarantee access. Limiting access using scope means another file/module can just add a property/function to make the value public. Confusing type-based and file-based access is a step backwards, and any attempt to add type-based access shouldn't be a breaking change.

Replacing internal with private(module) also seems like a step backwards, to me, and in my opinion changes to the ‘internal’ keyword should be part of a separate proposal.

Inherited & declaration modifiers compose well with existing access-modifiers, are clear in their purpose, can be applied to all access levels, and don't break existing code.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <CAPUwzK7YHzwDMTMuH1Qvbojz3+9+ikgJvna3xDhscESVO8YSNQ@mail.gmail.com>

It's occurring to me, reading these recent posts, that we have two
orthogonal systems of access levels.

Swift's current access system is file based; a project file decides which
files comprise a module, and the terms 'public', 'internal' and 'private'
determine whether a property is accessible to all, accessible only within
files of the module, or accessible only within a file. (This takes on an
extra dimension as files may belong to several modules).

The concept which began this discussion, and several of the proposed
concepts in this discussion, ask instead for a type-based access system
similar to those in other languages including Objective-C, where 'public',
'protected' and 'private' are the terms of choice and they restrict access
to a type or subtypes.

I think it would be confusing if Swift applied 'public' to a concept in the
file-based access system and 'private' to a concept in the type-based
access system.

I would prefer clearer terms which actually mention the restrictions of the
level. For example, 'inherited', not 'protected', in the case of properties
accessible by a class and its subclasses; 'declaration', rather than
'private' or 'scoped', to refer to properties only accessible within a
given type or extension declaration.

Since, at the moment, a declaration can only occur within one file, I think
this most-restricted level has managed to pass as a level of the file-based
access system. However, if the system is ever extended, we're going to run
into new syntax decisions where we have 'private module' functions
(accessible only within the given type in the same module) trying to
communicate with 'protected file' properties (accessible only with the type
and its subtypes in the same file), and that might lead to conflicts, so
perhaps we should decide how those might be declared now.

On Tue, Mar 15, 2016 at 11:51 PM, Jonathan Hull via swift-evolution < >> swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:

>On Tue, Mar 15, 2016 at 2:33 PM Erica Sadun <erica at ericasadun.com <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:
>
>And again, moving the access control modification to the end just doesn't look
>right to me or seem to enhance readability. :frowning:
>
>I like Shawn’s proposal better for cases where there are custom
>getter/setter implementations. We should definitely be able to do:
>
>var foo:Int {
>public get {…}
>private(file) set {…}
>}
>
>In fact, that is what I first tried to do before learning about
>private(set). But without the implementations, it just seems strange to
>put the scoping after the rest of the declaration (they work above because
>they are *before* the custom getter/setter).
>
>I still like the idea of having the option to use parameter-like syntax
>for cases where you don’t have custom getters/setters:
>
>private var foo:Int
>private(file) var foo:Int
>private(set: file) var foo:Int
>private(get: global, set: file) var foo:Int
>
>
>I guess, if we had some way to represent the standard getter/setter, that
>might work too. I don’t love it, but maybe with better wording?
>
>var foo:Int{
>public get useDefault
>private(file) set {…}
>}
>
>Thanks,
>Jon
>
>
>On Mar 14, 2016, at 10:22 PM, Patrick Pijnappel < >> >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>I like Shawn's proposal:
>
>
>
>var foo: Int { private(file) set }
>
>
>>In fact it's probably more sensible than the current private(set) IMO.
>
>
>For example, we already use
>
>var foo: Int { mutating get { ... } }
>
>and not
>
>mutating(get) var foo: Int { get { ... } }
>
>On Tue, Mar 15, 2016 at 4:13 PM, Patrick Pijnappel < >> >patrickpijnappel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
>>I like Shawn's proposal:
>>
>>var foo: Int { private(file) set }
>>
>>In fact it's probably more sensible than the current private(set) IMO.
>>
>>
>>While I like private(get: file, set: module) idea, I think it just gets
>>too inconsistent with private(set: public) and private(set: private) (?!)
>>
>>On Tue, Mar 15, 2016 at 3:39 PM, Jonathan Hull via swift-evolution < >> >>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org> wrote:
>>
>>>*On Mar 14, 2016, at 8:36 PM, Patrick Pijnappel via swift-evolution <swift-evolution at swift.org <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:*
>>>
>>>The only question is (as Sean mentioned) how this combines with the syntax
>>>for setter access level, e.g. the current private(set). Options:
>>>- Unnamed 2nd argument, giving private(file), private(file, set),
>>>private(set).
>>>- Named 2nd argument, giving e.g. private(file), private(file, accessor:
>>>set), private(accessor: set). Less ambiguity but longer.
>>>- Not using multiple arguments, but that'd probably break consistency with
>>>the other unification efforts going on to make everything look like
>>>function calls.
>>>
>>>What about the following 3 forms?
>>>
>>>private(file) //both setter and getter have file scope
>>>private(set: file) //setter has file scope. Equivalent to current
>>>“private(set)"
>>>private(get: module, set: file) //getter has module scope & setter has
>>>file scope
>>>
>>>It is a bit weird, but we should probably also allow “public" in that
>>>last form: private(get: public, set: module)
>>>
>>>Thanks,
>>>Jon
>>>
>>>_______________________________________________
>>>swift-evolution mailing list
>>>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
>>>https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>
>
>
>_______________________________________________
>swift-evolution mailing list
>swift-evolution-m3FHrko0VLzYtjvyW6yDsg@public.gmane.org
>https://lists.swift.org/mailman/listinfo/swift-evolution
>
>

------------- End Message -------------

From James F
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution