Type-based ‘private’ access within a file


(Douglas Gregor) #1

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug


(Daniel Duan) #2

I’m concerned that we will have access control changes in a future version yet again, when light-weight modules, or other type of enforced namespace is introduced. Does the core team have any foresight on how this change would interact with such things? I had the same concern for SE-0159 as well.

There’s a implicit drawback to all access control changes that migrator/fix-its cannot fix: we organize our code with tools in the language. Some colleague of mine had came up with schemes that combines file scope and Swift 3 `private` to hide details among separate protocol extensions, for example. Code ends up in certain places for a reason and updating access control invalidate those reasons.

I hesitate to support any changes until we have some ideas for what “ultimate glory” looks like.

···

On Apr 3, 2017, at 11:34 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charles Srstka) #3

This appears similar to an idea I brought up during the SE-0159 discussion:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034156.html
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034162.html

I feel that, while imperfect, the idea would provide a compromise between those of us who prefer to have a scoped access level, and those who feel encumbered by ‘private’ not applying to in-file extensions. Therefore, I’d be generally +1 on it.

Charles

···

On Apr 3, 2017, at 1:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?


(Zachary Waldowski) #4

Depending on the actual implications of the loosening of `private`, I'd
then advocate for deprecating `fileprivate` in the Swift 4 timeframe and
removing when it makes sense. Is that an option?

I am personally against muddying the implementation of access control
further (in addition to its existing muddying in the syntactical sense,
but let's avoid rehashing that now), and would like it if someone from
the Core Team could speak to the complexities involved there. I wouldn't
want access control changes to, for instance, hurt compile times or
stymie ABI efforts.

Sincerely,

  Zachary Waldowski

  zach@waldowski.me

···

On Mon, Apr 3, 2017, at 02:34 PM, Douglas Gregor via swift-evolution wrote:

Hello Swift Community,

In rejecting SE-0159[1], the core team described a potential direction
we would like to investigate for “private” access control that admits
a limited form of type-based access control within files. The core
team is seeking some discussion here and a motivated volunteer to put
together a proposal along these lines for review in the Swift 4 time-
frame (i.e., very soon). To be clear, the core team it’s sure this is
the right direction to go… but it appears promising and we would
*love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a
type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file

* The definition of “X”, if it occurs in the same file

* A nested type (or extension thereof) of one of the above that occurs
  in the same file

This design has a number of apparent benefits:

+ “private” becomes the right default for “less than whole module”
  visibility, and aligns well with Swift coding style that divides a
  type’s definition into a number of extensions.
+ “fileprivate” remains for existing use cases, but now it’s use it
  more rare, which has several advantages:
+ It fits well with the "progressive disclosure” philosophy behind
  Swift: you can use public/internal/private for a while before
  encountering and having to learn about “fileprivate” (note: we
  thought this was going to be true of SE-0025[2], but we were clearly
  wrong)
+ When “fileprivate” occurs, it means there’s some interesting
  coupling between different types in the same file. That makes
  fileprivate a useful alert to the reader rather than, potentially,
  something that we routinely use and overlook so that we can separate
  implementations into extensions.
+ “private” is more closely aligned with other programming languages
  that use type-based access control, which can help programmers just
  coming to Swift. When they reach for “private”, they’re likely to
  get something similar to what they expect—with a little Swift twist
  due to Swift’s heavy use of extensions.
+ Loosening the access restrictions on “private” is unlikely to break
  existing code.

There are likely some drawbacks:

- Developers using patterns that depend on the existing lexically-
  scoped access control of “private” may find this new interpretation
  of “private” to be insufficiently strict
- Swift’s access control would go from “entirely lexical” to “partly
  lexical and partly type-based”, which can be viewed as being more
  complicated

Thoughts? Volunteer?

- Doug

_________________________________________________

swift-evolution mailing list

swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution

Links:

  1. https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
  2. https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md


(Austin Zheng) #5

I am a reluctant -1. If rejecting 159 was the right course of action to avoid unnecessary churn, I think that any further modification to the access control system should come as part of a comprehensive modules/namespaces/code organization proposal. Extracting a bit of progressive disclosure from yet another change in the rules really doesn’t seem worth the cost of developers having to relearn what access control does yet again.

Best,
Austin

···

On Apr 3, 2017, at 2:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Waite) #6

Soft -1 for four reasons:

1. I would expect private to be used to hide implementation details and type invariants from all code, to encapsulate and protect the unsafe bits. Think the possibility to put the instance into an illegal state, or to modify its state outside of its defined threading model. Why would an extension be trusted to do this? This smacks of a ‘protected’ mode for extensions.

2. This makes the model more confusing, and increases overlap with file private. It seems this is here just to appease the people who think “fileprivate” is an ugly wart, while not having time to formulate a strategy to eliminate file private. The real issue is that there isn’t a level between fileprivate and internal.

3. This seems to make the issue of large files even worse, by encouraging the use of ‘private’ as a way of exposing an extension-specific API of a type that is only accessible by putting extensions in the same file

4. From discussions on migration, I believe we can leave the option open of widening private later as part of a tasked redesign of access control after Swift 4.0. I’d prefer to not widen private before we have evaluated access control as a whole, as I believe private as it is today is the lowest, most restrictive-but-usable level of access control.

-DW

···

On Apr 3, 2017, at 12:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charlie Monroe) #7

For me, -1 for two reasons:

- Mainly, it still encourages stuffing everything into one file. I don't claim that having a 50-line files is the goal, but neither is having 1500 lines of code within one file. With less complex types, you're mostly fine with private/fileprivate as they are. For more complex types, you want to split the type across a few files making it better readable and organized. This doesn't help.

- I feel this brings more confusion/rules to the private/fileprivate access control without actually solving issues I personally run into with Swift access control...

···

On Apr 3, 2017, at 8:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Zubarev) #8

I must admit that’s a very interesting approach, however to me it feels like fileprivate will be a really small upgrade to private when you actually need it. Plus you could almost do everything with fileprivate instead of private. As Carlie Monroe said it will create a new source for confusion.

···

--
Adrian Zubarev
Sent with Airmail

Am 3. April 2017 um 20:35:05, Douglas Gregor via swift-evolution (swift-evolution@swift.org) schrieb:

Hello Swift Community,

In rejecting SE-0159, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file
* The definition of “X”, if it occurs in the same file
* A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
+ “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
+ “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
+ It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025, but we were clearly wrong)
+ When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
+ “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
+ Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
- Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
- Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

- Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #9

While I am disappointed that SE-0159 got rejected, this alternative would resolve most issues I have with the current model. It would allow us to once again use private as a good default.

I really care about this topic so I volunteer for writing the proposal if nobody feels strongly about it.

Btw, I know what I'm going to propose is a bit crazy, but how about making private visible to extensions even outside the file but in the same module?

David.

···

On 3 Apr 2017, at 20:34, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #10

Here’s an early draft of the proposal. Please fire away with comments! By the way, how would the visibility in subclasses in the same file be handled?

https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md

Type-based Private Access Level

Proposal: SE-XXXX <https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md>
Authors: David Hart <http://github.com/hartbit>
Review Manager: TBD
Status: TBD
<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#introduction>Introduction

This proposal extends the visibility of the private access level to all extensions, declarations and nested types in the same file.

<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#motivation>Motivation

Proposal SE-0025 <https://github.com/hartbit/swift-evolution/blob/type-private/proposals/0025-scoped-access-level.md> introduced a lexically-scoped access level named private and renamed the file-based access level to fileprivate. The hope was for private to be a good default for restricting visibility further than the whole module and for fileprivate to be used in rarer occasions when that restriction needed to be loosened.

Unfortunately, that goal of the proposal has not been realized: Swift's reliance on extensions as a grouping and conformance mechanism has made fileprivate more necessary than expected and has caused more friction between private and fileprivate than intended.

As a consequence, experience with using Swift 3 has caused mixed reactions from the mailing list and greater Swift community, culminating in proposal SE-0159 <https://github.com/hartbit/swift-evolution/blob/type-private/proposals/0159-fix-private-access-levels.md> which suggested reverting the access level changes. That proposal was rejected to continue supporting the code written since Swift 3 which benefits from the distinction between private and fileprivate, but it was recognized that the language's lack of a good default access level more restictive than internal was unfortunate.

In the hopes of fulfilling the initial goal of SE-0025 <https://github.com/hartbit/swift-evolution/blob/type-private/proposals/0025-scoped-access-level.md>, this proposal defines the visibility of the private access level to extensions, declarations and nested types of the member's type in the same file to increase its usefulness and as a good default private access level. fileprivate then logically achieves its intended goal of being more rarely used and adheres to Swift's "progressive disclosure” philosophy.

<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#detailed-design>Detailed design

The design of this proposal defines the visibility of a private member declared within a type X or an extension of type X to:

the declaration of X if it occurs in the same file
all extensions of X or subclasses of X in the same file
all declarations of nested types of X in the same file
all extensions of nested types of X in the same file
To illustrate the consequence of those rules, the following examples will be used with two files in the same module:

<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#personswift>Person.swift

struct Person {
    let name: String
    let gender: Gender
    private let age: String

    var greeting {
        return "Hello, my name is \(name)"
    }

    init(name: String, gender: Gender, age: String) {
        self.name = name
        self.age = age
    }

    func greet() {
        // age is accessible because it is defined in the same declaration but secreyAge is not because it is defined
        // in a nested type so the following piece of code would generate a compilation error:
        // if age < gender.secrecyAge {
        // instead:
        if Gender.shouldRevealAge(self) {
            // fullGreeting is accessible because it is defined in an
            // extension of the same type in the same file
            print(fullGreeting)
        } else {
            print(greeting)
        }
    }
}

// private at the top-level scope continues to be equivalent to fileprivate
private extension Person {
    // fullGreeting is implictly private due to the extension's modifier
    var fullGreeting: String {
        // age is accessible because it is defined in the declaration of the extension's type in the same file
        return "Hello, my name is \(name), I'm \(age) years old."
    }
}

extension Person {
    enum Gender {
        case male
        case female

        private var secrecyAge {
            switch self {
            case .male: return 60
            case .female: return 50
            }
        }

        static func shouldRevealAge(_ person: Person) -> Bool {
            // age is accessible because we are in the declaration of a nested type that declared age
            return person.age < person.gender.secrecyAge
        }
    }
}

extension Gender {
    static func leakAge(of person: Person) {
        // age is accessible because we are in the extension of a nested type in the same file
        return person.age
    }
}
<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#otherswift>Other.swift

extension Person : CustomStringConvertible {
    var desription: String {
        return fullGreeting
        // error: fullGreeting is not available because it is defined in another file
    }
}
<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#source-compatibility>Source compatibility

Incoming...

<https://github.com/hartbit/swift-evolution/blob/type-private/proposals/XXXX-typed-based-private.md#alternatives-considered>Alternatives Considered

Incoming...

···

On 3 Apr 2017, at 20:34, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Víctor Pimentel) #11

Strongly +1, and I fully agree with David Hart draft.

As an app developer that works with Swift everyday, this will fix most of
my pain-points with scoped access. It will not only ease a very popular use
of extensions, but when asking a new developer this is the default that
makes more sense.

Being selfish, with this proposal, you could even delete fileprivate, I
would never use it or recommend it. If you want a type private to a file,
enclose it under other type.

···

On Mon, Apr 3, 2017 at 8:34 PM, Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

The design, specifically, is that a “private” member declared within a
type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file
* The definition of “X”, if it occurs in the same file
* A nested type (or extension thereof) of one of the above that occurs in
the same file

--
Víctor Pimentel


(Chris Lattner) #12

Another way to explain this is as a relaxation of the Swift 3 access control, to would allow private members in a type to also be accessible in extensions to that type, so long as they are in the same file.

While I typically try to avoid chiming in on early discussions like this, I pretty strongly believe that this is a good solution for the reasons you mention:

- fileprivate should really become much more rare, which makes it more meaningful and significant where it occurs. This was the original idea and intent behind SE-0025.

- Similarly, this simplifies access control for most people. Most people will now only care about private/internal/public. fileprivate will become an expert feature used in specific cases to solve a specific class of problems. Progressive disclosure of complexity is important.

- This design is true to the existing design of Swift: we want to encourage the implementation of types to be freely broken into extensions. This alignment with extension oriented programming was the one important virtue of the Swift 1/2 access control design that Swift 3 lost.

From a pragmatic perspective, I feel like this is a great solution that really does solve the problems we have with current access control, all without breaking source compatibility. This is also a major progression from where we are, and doesn’t appear to cut off any future directions (e.g. submodules) since those are cross-file concepts that live between internal/public or between fileprivate/internal.

Just MHO, but I think that the rhetorical attempts to paint this as being similar to “protected” are unsound.

-Chris

···

On Apr 3, 2017, at 11:34 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file


(Aaron Crespo) #13

I'm in favor of this as an alternative to the previous evolution. Having
worked on Swift projects I find that using `private` ends up being very
rare when using an extension based style, good intentions and `private`
definitions soon convert to `fileprivate` and never back. I think the goal
of progressive discovery and trying make the simplest most obvious case
work more often breaks down with respect to access control and an extension
based architecture. This was not the case in Swift 2 when `internal` and
`private` covered everything well with an extension based style. Having
mentored people learning swift this is a very surprising discovery, in a
language that tries to not be surprising. Barring the revert which I was in
favor of this should go a ways to making `private` more useful more often
and making `fileprivate` an advanced form of `private` (as intended)? and
more rarely used.

···

On Mon, Apr 3, 2017 at 2:34 PM, Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159
<https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>,
the core team described a potential direction we would like to investigate
for “private” access control that admits a limited form of type-based
access control within files. The core team is seeking some discussion here
and a motivated volunteer to put together a proposal along these lines for
review in the Swift 4 time-frame (i.e., very soon). To be clear, the core
team it’s sure this is the right direction to go… but it appears promising
and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a
type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file
* The definition of “X”, if it occurs in the same file
* A nested type (or extension thereof) of one of the above that occurs in
the same file

This design has a number of apparent benefits:
+ “private” becomes the right default for “less than whole module”
visibility, and aligns well with Swift coding style that divides a type’s
definition into a number of extensions.
+ “fileprivate” remains for existing use cases, but now it’s use it more
rare, which has several advantages:
+ It fits well with the "progressive disclosure” philosophy behind Swift:
you can use public/internal/private for a while before encountering and
having to learn about “fileprivate” (note: we thought this was going to
be true of SE-0025
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>,
but we were clearly wrong)
+ When “fileprivate” occurs, it means there’s some interesting coupling
between different types in the same file. That makes fileprivate a useful
alert to the reader rather than, potentially, something that we routinely
use and overlook so that we can separate implementations into extensions.
+ “private” is more closely aligned with other programming languages that
use type-based access control, which can help programmers just coming to
Swift. When they reach for “private”, they’re likely to get something
similar to what they expect—with a little Swift twist due to Swift’s heavy
use of extensions.
+ Loosening the access restrictions on “private” is unlikely to break
existing code.

There are likely some drawbacks:
- Developers using patterns that depend on the existing lexically-scoped
access control of “private” may find this new interpretation of “private”
to be insufficiently strict
- Swift’s access control would go from “entirely lexical” to “partly
lexical and partly type-based”, which can be viewed as being more
complicated

Thoughts? Volunteer?

- Doug

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


(Colin Barrett) #14

I'm broadly in favor of this.

Hello Swift Community,

In rejecting SE-0159
<https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>,
the core team described a potential direction we would like to investigate
for “private” access control that admits a limited form of type-based
access control within files. The core team is seeking some discussion here
and a motivated volunteer to put together a proposal along these lines for
review in the Swift 4 time-frame (i.e., very soon). To be clear, the core
team it’s sure this is the right direction to go… but it appears promising
and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a
type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file
* The definition of “X”, if it occurs in the same file
* A nested type (or extension thereof) of one of the above that occurs in
the same file

This design has a number of apparent benefits:
+ “private” becomes the right default for “less than whole module”
visibility, and aligns well with Swift coding style that divides a type’s
definition into a number of extensions.
+ “fileprivate” remains for existing use cases, but now it’s use it more
rare, which has several advantages:
+ It fits well with the "progressive disclosure” philosophy behind Swift:
you can use public/internal/private for a while before encountering and
having to learn about “fileprivate” (note: we thought this was going to
be true of SE-0025
<https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>,
but we were clearly wrong)
+ When “fileprivate” occurs, it means there’s some interesting coupling
between different types in the same file. That makes fileprivate a useful
alert to the reader rather than, potentially, something that we routinely
use and overlook so that we can separate implementations into extensions.
+ “private” is more closely aligned with other programming languages that
use type-based access control, which can help programmers just coming to
Swift. When they reach for “private”, they’re likely to get something
similar to what they expect—with a little Swift twist due to Swift’s heavy
use of extensions.
+ Loosening the access restrictions on “private” is unlikely to break
existing code.

There are likely some drawbacks:
- Developers using patterns that depend on the existing lexically-scoped
access control of “private” may find this new interpretation of “private”
to be insufficiently strict
- Swift’s access control would go from “entirely lexical” to “partly
lexical and partly type-based”, which can be viewed as being more
complicated

I think it might not as complicated as it may first appear. I haven't fully
convinced myself of this, but I believe that it would be lexically
scoped *modulo
inlining extensions*.

To put it somewhat more formally (and awkwardly), if one imagines a textual
transformation which blindly inlines any extension in a single file into
their type definitions (should those definitions occur within that file)
then accessing a "private" member in the original file would compile if and
only if the access would be lexically scoped if the above postulated
transformation were to be applied to it.

This is a pleasing property (to me anyway) as it means that it is unlikely
(impossible?) for moving code from one extension (or definition) to another
to cause a compilation failure.

Take this with a grain of salt of course, as there's probably an edge case
I'm not thinking of :stuck_out_tongue: (This is why we write proofs!)

Cheers,
-Colin

···

On Mon, Apr 3, 2017 at 2:35 PM Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:

Thoughts? Volunteer?

- Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jordan Rose) #15

Hi, -evolution. I’ve said this before, but I think this new proposal is a terrible idea. It privileges types in a way that is damaging to the language.

[There isn't really anything new in my discussion below; everyone on-thread is smart enough to have brought up these points already. But I wanted to go on record about it, at least.]

The claimed problem with the current version of 'private' (let's call it "scoped-private") is that it encourages developers to make monolithic type declarations instead of using extensions. With the proposed new interpretation (let's call it "extension-file-private"), there's a similar problem: developers are encouraged to put everything in the original type even when it may be more appropriate to

1. Extend another type (e.g. converting initializers)
2. Use a helper type (a nested type always inherits the generic parameters of its enclosing type)
3. Break a single protocol or class out into a hierarchy (subtyping should be used sparingly but not never)

Of course, one can always add an extension to access the extension-file-private members from outside the type, but that just underscores how little expressive power this level would actually have. These are cases where 'fileprivate' is the correct tool for the job.

I liked the original three levels of access (not a surprise to anyone, since I was a primary designer), and one reason for that is that the access levels are completely indepedent of the declarations you're writing. You can organize your code in whatever way makes the most sense, and the access levels will then help you enforce that organization. I do think SE-0025 should not have been accepted, that it does not add enough benefit given the increase to complexity, but even scoped-private can be used as an organizational feature that prevents you from making mistakes, and it still offers a simple answer to where a declaration can be used.

The proposed extension-file-private exposes a declaration to an arbitrary subset of the file it's in, because being within an extension of a type or not is arbitrary with regards to code organization. Extensions are used organizationally, but there's now no way to distinguish whether the private members of this extension are related to the private members of that extension, or whether they were supposed to be independent.

Everyone is acting like "fileprivate" is a problem. While we may not like the name, it's still the right tool for the job. What else do you have in the file that you're trying to protect?

Let's not add a mishmash of a feature just because it's "practical" for some uses.

Thanks for hearing me out,
Jordan

P.S. I have a lot to say on the idea of "submodules", and the dozen different things people want from them. I'll try to write that up later, so that people can refer to it if/when we ever get around to discussing such features. But it's not relevant right now.


(BJ Homer) #16

-0.5

SE-0159 was rejected because it was determined that some developers are actively using strongly-scoped access control. This proposal removes that strong scoping, so I do not see how we can reasonably reject that proposal but accept this one.

The entire reason we're having this discussion is that "fileprivate" is such an awkward term for something that's so common in the language. I think the main thing we need to fix is the naming of that keyword.

I continue to believe that the best solution is to revert "private" to mean file scope as in Swift 2, and introduce a new "scoped" keyword for those developers who are specifically desiring the scoped functionality. This was rejected during the discussion because the migration would be too disruptive, but it is only disruptive if the migrator rewrites "private"->"scoped". I assert that most developers would not *want* that migration to happen; most developers use "private" because they want the default less-than-internal access control. The few developers who are using specifically scoped control can modify their code manually. Under this model, scoped access control is still available for those who need it, and most users can once again use "private" in cases where it is the natural default.

This proposal proposes that "fileprivate" would become a marker to call out cases where exceptional across-type access is happening. In practice, I don't believe that will happen, simply because there are many existing cases of "fileprivate" out there, and this proposal does not suggest migrating them.

I also disagree that it's useful to call out "fileprivate" as an exceptional case. It's slightly useful, I'll acknowledge, but it would be *more* useful to call out the exceptional cases where scope-only control is being used.

So I disagree with the proposal. But I give it only -0.5 because even with all of that, this is a better definition for "private" than the current one.

-BJ

···

On Apr 3, 2017, at 12:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charles Srstka) #17

That’s kind of the point, though; to reduce ‘fileprivate’ to something that is rarely ever used.

Charles

···

On Apr 3, 2017, at 2:00 PM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

I must admit that’s a very interesting approach, however to me it feels like fileprivate will be a really small upgrade to private when you actually need it.


(Charles Srstka) #18

That’s actually what I suggested in my original post on the topic. My feeling was that it would allow breaking a particularly large type into separate files, thus alleviating the “huge file” problem that Swift has (and which Charlie Monroe brought up as a concern).

It’s still what I’d prefer personally, although I can understand why the core team might want to restrict it to files.

Charles

···

On Apr 3, 2017, at 2:28 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Btw, I know what I'm going to propose is a bit crazy, but how about making private visible to extensions even outside the file but in the same module?


(Matthew Johnson) #19

I’m concerned that we will have access control changes in a future version yet again, when light-weight modules, or other type of enforced namespace is introduced. Does the core team have any foresight on how this change would interact with such things? I had the same concern for SE-0159 as well.

There’s a implicit drawback to all access control changes that migrator/fix-its cannot fix: we organize our code with tools in the language. Some colleague of mine had came up with schemes that combines file scope and Swift 3 `private` to hide details among separate protocol extensions, for example. Code ends up in certain places for a reason and updating access control invalidate those reasons.

I hesitate to support any changes until we have some ideas for what “ultimate glory” looks like.

+1.

If we must make a change in Swift 4, the only change I can support for Swift 4 is renaming the existing access levels. That would cause some churn but can be automated and has no semantic impact. I feel strongly that the semantics of access control should remain the same until submodules and access control can be considered together as part of the theme of a larger Swift release. I believe the churn caused by continuing to poke at the semantics of access control without addressing the broader issues would be a mistake that would cause further frustration in the community.

As others have already pointed out, code has been developed and organized with the new scoped access model in mind. I think the frustration over a semantically neutral, fully automated migration to new names would be pretty minimal and certainly much less than the frustration over the suggested semantic change.

Renaming would restore the original intent of SE-0025 which was to leave private alone and introduce a new name for scoped access. One of the big reasons that approach was rejected is that we did not have consensus on what to call it. Now that we seem to have reached consensus about what the name should be if it is changed it is reasonable to correct the mistake that was made in Swift 3.

Finally, I am not at all convinced that type-based private is the right semantics. I think the strictly hierarchical foundation of the existing access levels is a much stronger design. The suggested proposal for a same-file type-based approach has already resulted in requests for expanding that model to the whole module. Types and scopes are orthogonal dimensions. If we want to consider a hybrid model for access control I think it is best not to rush. We should take our time and consider it properly in the future.

···

On Apr 3, 2017, at 2:55 PM, Daniel Duan via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 11:34 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swift Community,

In rejecting SE-0159 <https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md>, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

  * An extension of “X” in the same file
  * The definition of “X”, if it occurs in the same file
  * A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
  + “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
  + “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
    + It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025 <https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md>, but we were clearly wrong)
    + When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
  + “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
  + Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
  - Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
  - Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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


(Jarod Long) #20

Pretty bummed out about the rejection. I know it's a petty aesthetic issue, but thinking about having to write "fileprivate" 5 or 10 years from now kills more of my enthusiasm about using the language than I'd like to admit. I think it's going to always be viewed by most as a major wart on an otherwise great language. Hopefully we can be more careful in the future about letting this sort of thing get through in the first place.

All that said, I'll support a proposal along the lines of what's being suggested.

Jarod

···

On Apr 3, 2017, at 12:34 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community,

In rejecting SE-0159, the core team described a potential direction we would like to investigate for “private” access control that admits a limited form of type-based access control within files. The core team is seeking some discussion here and a motivated volunteer to put together a proposal along these lines for review in the Swift 4 time-frame (i.e., very soon). To be clear, the core team it’s sure this is the right direction to go… but it appears promising and we would *love* to be able to settle the access-control issue.

The design, specifically, is that a “private” member declared within a type “X” or an extension thereof would be accessible from:

* An extension of “X” in the same file
* The definition of “X”, if it occurs in the same file
* A nested type (or extension thereof) of one of the above that occurs in the same file

This design has a number of apparent benefits:
+ “private” becomes the right default for “less than whole module” visibility, and aligns well with Swift coding style that divides a type’s definition into a number of extensions.
+ “fileprivate” remains for existing use cases, but now it’s use it more rare, which has several advantages:
+ It fits well with the "progressive disclosure” philosophy behind Swift: you can use public/internal/private for a while before encountering and having to learn about “fileprivate” (note: we thought this was going to be true of SE-0025, but we were clearly wrong)
+ When “fileprivate” occurs, it means there’s some interesting coupling between different types in the same file. That makes fileprivate a useful alert to the reader rather than, potentially, something that we routinely use and overlook so that we can separate implementations into extensions.
+ “private” is more closely aligned with other programming languages that use type-based access control, which can help programmers just coming to Swift. When they reach for “private”, they’re likely to get something similar to what they expect—with a little Swift twist due to Swift’s heavy use of extensions.
+ Loosening the access restrictions on “private” is unlikely to break existing code.

There are likely some drawbacks:
- Developers using patterns that depend on the existing lexically-scoped access control of “private” may find this new interpretation of “private” to be insufficiently strict
- Swift’s access control would go from “entirely lexical” to “partly lexical and partly type-based”, which can be viewed as being more complicated

Thoughts? Volunteer?

- Doug
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution