Type-based ‘private’ access within a file

This type-and-file-based proposal addresses most of the *pragmatic* issues people run into when writing Swift, but I agree with other comments that it's a difficult mental model.

It sounds like most everyone likes the idea of renaming "private" -> "scoped" and "fileprivate" -> "private", but the code churn is considered too large for Swift 4. What about the following alternative, which is similar to SE-0159 but avoids the code churn:

- Revert the meaning of "private" to the Swift 2 meaning, as in SE-0159.
- Make "fileprivate" an alias for "private", as in SE-0159
- Migrator converts "fileprivate" -> "private", as in SE-0159
- Introduce "scoped", but perform no automatic migration for it.

The discussion around SE-0159 has shown that there are indeed important use cases for scoped access control. However, most instances of "private" in the wild are probably just due to its position as a "soft default", and don't need any migration. Developers who are relying on scoped access control are likely to be aware of locations where it is important, and could manually rewrite "private" to "scoped" for those sites. (For users who want to perform a full migration of "private" -> "scoped", perhaps a manual migration script could be provided.)

It's somewhat unfortunate to require manual migration to "scoped" for code that cares about scoped access, but I suggest that those use cases are rare and the developers are generally aware of such cases. This proposal prefers to limit the code churn instead, while getting rid of the "fileprivate" wart on the language. Most users would be able to migrate to Swift 4 with only the amount of migration already proposed in SE-0159.

-BJ

···

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, 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

I mean an upgrade from private, please don’t get me wrong there for that typo.

···

--
Adrian Zubarev
Sent with Airmail

Am 3. April 2017 um 21:00:26, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

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

I agree. If someone made a fork of Swift whose only difference was to
change the spellings to “private” and “scoped”, and there was a way to use
it with Xcode, then I would use that instead of the official version in a
heartbeat. Heck, if someone made a preprocessor that just replaced the
access modifiers before compiling, I’d jump at the chance to use it.

My remaining hope is that Swift will acquire a submodule design which
renders “fileprivate” essentially redundant. If we get an access level that
means “visible in a group of tightly-related files” and it has a concise
spelling, then I will use that just about exclusively. If a file is not
explicitly part of a submodule then that new level would be synonymous with
“fileprivate”, and if it is in a submodule then that level is exactly what
I want anyway, so I can split up tightly-coupled implementations into
separate files.

I don’t know what the spelling for that access level would be, but if we
can find a good one then I’ll be happy to never have to type “fileprivate”
again.

Nevin

···

On Mon, Apr 3, 2017 at 8:26 PM, Jarod Long via swift-evolution < swift-evolution@swift.org> wrote:

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.

The problem I see with that is that it would introduce orthogonal access levels whereas they have all been hierarchal in nature up to now.

···

On 3 Apr 2017, at 21:36, Charles Srstka <cocoadev@charlessoft.com> wrote:

On Apr 3, 2017, at 2:28 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto: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?

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

FWIW, I think this is the way to go. It’s also more in line with other languages and how they handle “class internal”. The only one that should care about the file is fileprivate, and I honestly think I’d never wind up using that if private were fixed properly (current type + same-module extensions + any file).

— Adam

···

On Apr 3, 2017, at 2:36 PM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 2:28 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto: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?

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.

Yeah I think the best course of action is to leave things alone until such
time as we can more holistically work things as you outline.

Folks can strive to use private as the default lesser then module access
level with fileprivate remaining available for those code patterns that
require it for now (e.g. falling back on using the IMHO crutch of file
co-residency).

···

On Mon, Apr 3, 2017 at 1:28 PM Austin Zheng via swift-evolution < swift-evolution@swift.org> wrote:

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&gt;,
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&gt;,
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

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

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.

Not everybody would hate that ;), but seriously it seemed a strong request in all our discussions about this and it comes at a very small cost.

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.

I am not sure this kind of change will easily happen for Swift 5, I say let's not waste this chance.

···

Sent from my iPhone

On 4 Apr 2017, at 01:01, David Waite via swift-evolution <swift-evolution@swift.org> wrote:

-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, 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

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

Can we get a clear answer from the core team as to whether a redesign of access control is going to be permitted post Swift 4.0? There are a few replies in this thread that are insinuating that no further changes will be permitted.

-Tony

···

On 4 Apr 2017, at 10:01, David Waite via swift-evolution <swift-evolution@swift.org> wrote:

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.

----------
Tony Arnold
+61 411 268 532
http://thecocoabots.com/

ABN: 14831833541

This type-and-file-based proposal addresses most of the *pragmatic* issues
people run into when writing Swift, but I agree with other comments that
it's a difficult mental model.

It sounds like most everyone likes the idea of renaming "private" ->
"scoped" and "fileprivate" -> "private", but the code churn is considered
too large for Swift 4. What about the following alternative, which is
similar to SE-0159 but avoids the code churn:

- Revert the meaning of "private" to the Swift 2 meaning, as in SE-0159.
- Make "fileprivate" an alias for "private", as in SE-0159
- Migrator converts "fileprivate" -> "private", as in SE-0159
- Introduce "scoped", but perform no automatic migration for it.

FWIW Currently I believe this is the best alternative/compromise we can have. I think anyone who defer the current scoped 'private' is OK to manually change it to 'scoped' in new version of Swift.
And those who support SE-0159 will have Swift 2.0 'private'. As for fileprivate probably it should be marked as deprecated so we can later remove it from language.

Actually I'm very surprised :-( of core team decision and ultimate reaction on community's loud request to rename fileprivate->private and current private->scoped to achieve the both targets(to have Swift 2 'private' instead of 'fileprivate' and keep the usefull current 'private' access level). In addition it was said that it is the last chance to change anything in access modifiers. IMO this BJ Homer's solution/compromise is the way we *should* go given that this is *the last chance* to improve the situation with access modifiers.
As was said by core team, there will be no *any* reconsideration on access levels/keywords after this, even for submodules etc. And core team even did not discussed a lot features like submodules in the light of access modifiers(they said this).

I want to ask/recommend anyone who want to improve the situation with access modifiers - reply to BJ Homer's message with support for it, so core team can see the consolidated opinion they can take into account.

···

On 04.04.2017 5:03, BJ Homer via swift-evolution wrote:

The discussion around SE-0159 has shown that there are indeed important use
cases for scoped access control. However, most instances of "private" in
the wild are probably just due to its position as a "soft default", and
don't need any migration. Developers who are relying on scoped access
control are likely to be aware of locations where it is important, and
could manually rewrite "private" to "scoped" for those sites. (For users
who want to perform a full migration of "private" -> "scoped", perhaps a
manual migration script could be provided.)

It's somewhat unfortunate to require manual migration to "scoped" for code
that cares about scoped access, but I suggest that those use cases are rare
and the developers are generally aware of such cases. This proposal prefers
to limit the code churn instead, while getting rid of the "fileprivate"
wart on the language. Most users would be able to migrate to Swift 4 with
only the amount of migration already proposed in SE-0159.

-BJ

On Apr 3, 2017, at 8:34 PM, 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&gt;,
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&gt;,
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

- 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.

I think this will end up being a flawed assumption, just like last time.

Granted: there will be less need for `fileprivate` with this. Files that implement a type will not need `fileprivate` regardless of how many extensions they use to implement the type. But note that if there is only one type defined in that file (as is often the case), `private` has absolutely the same meaning as `fileprivate`.

Files that extend multiple types for the purpose of implementing a particular feature will still require `fileprivate` if those extensions want to share some implementation details. Maybe we gain something by making this explicit with a special access level, but frankly I don't really see what those gains are.

- 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.

People who only care about private/internal/public and ignore `fileprivate` will thus be restricted when it comes to using extensions on multiple types at the same time. If using `fileprivate`indeed becomes rare or discouraged, this will shape the language away from such patterns.

- 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.

This cut both ways. We want to encourage the implementation of types being freely broken into extensions. Great!. But do we want to discourage features implemented as extensions that spans across multiple types?

I actually don't fear this will actually hamper this pattern much. People will just use `fileprivate` for these "rare" cases that actually aren't that rare. It's not that big of a problem. But that would mean the assumption is flawed.

On the other hand, if `fileprivate`effectively becomes a rarity, then it'll mean people are shying away from this pattern. In my opinion, that'd be unfortunate.

···

Le 5 avr. 2017 à 0:02, Chris Lattner via swift-evolution <swift-evolution@swift.org> a écrit :

--
Michel Fortin
https://michelf.ca

I would like to understand the reasoning here. I just looked back at
SE-0025 and I see this same assertion, but I cannot find the reasoning.
Could you explain it to me please?

Certainly I would love to make the *spelling* of “fileprivate” be entirely
nonexistent. But all the lines of logic I have come up with lead inexorably
to the conclusion that the *semantics* of “fileprivate” should be the
common, *de facto*, access level that people reach for when they need
encapsulation.

1. Someone makes a file with a single type in it, and marks the
implementation details “private”. At this point, it does not matter matter
which meaning “private” has, they all work the same so far.

2. The developer adds a free function to the file. Or an extension of
another type. Or another type entirely. And they put it in the same file
because it needs to work with the implementation details of the existing
type.

Now the difference between possible meanings of “private” matters. And if
it is anything short of “fileprivate”, then the developer has to go back
and change access levels. Things no longer “just work”.

The alternative scenario is that one adds something to the file which
doesn’t need privileged access to what’s already there. In which case the
questions are, “Why put it in the same file at all?” and “If there is a
good reason to put it in the same file, is there any *harm* in it being
able to see private members?”

Most developers most of the time should not have to think about
sub-file-level granularity. If things are in the same file it is because
they need to work together closely. We should be able to mark members
“private” and work with them across the file. This dramatically reduces the
cognitive burden, and the amount of time spent fiddling with access levels.

With any meaning of “private” less than “fileprivate”, developers end up
marking things “private”, then letting the IDE change it to “fileprivate”
when the compiler complains. This tells me that people actually want the
semantics of “fileprivate”, and they want it to be spelled “private”.

The main exception, where people truly desire and intend for
tighter-than-file encapsulation, is when certain invariants must be
preserved, and should not be touched except by dedicated methods. And
*that* is the important case worth making unambiguously explicit.

All the talk about calling out cross-type sharing within a file seems
superfluous. That is one of the principle reasons for putting multiple
types in one file to begin with. But preserving invariants, now *that*
deserves a meaningful and significant syntax, ideally something loud that
warns developers not to mess with it.

So, why exactly is there a desire to make the semantics of “fileprivate”
rare?

Nevin

···

On Wed, Apr 5, 2017 at 12:02 AM, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

- 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.

Hello Swift Community,

In rejecting SE-0159
<https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md&gt;,
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

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.

If we have Swift2's 'private' (instead of fileprivate) and 'scoped'(instead of current 'private'), then such 'private' can naturally mean "private to submodule" *especially* if file will be treated as un-named submodule.

What we'll have with 'fileprivate' to have a submodule-wide access? New keyword 'submoduleprivate' ? Will extend meaning of proposed 'private' ? Rename 'fileprivate' to something else?
Just wonder if this direction was really discussed and core team has some thoughts about this.

···

On 05.04.2017 7:02, Chris Lattner via swift-evolution wrote:

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

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

-Chris

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

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&gt;, 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&gt;, 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 :P (This is why we write proofs!)

This is a very interesting perspective Colin. This idea seems to align well with the intent for extensions that Chris stated earlier. This way of thinking about it does make the proposal much cleaner conceptually. If we’re going to adopt this perspective I think we should go all the way - same file extensions really should be inline semantically. This means same file extensions would also have the ability to include stored properties which is something many people have asked for.

I wonder how David and the core team would feel about modifying the proposal to adopt this “inline same file extensions" perspective. IMO this motivates the proposal better by acknowledging that most developers in the community use same file extensions for purely organization purposes. The implicit desire is that they be transparent boundaries that carry no semantic weight at all. I think a proposal with this kind of motivation is more likely to be well received by the broader community than a change that is only focused on access control in a very specific context. Instead of “why do they keep changing access control” the response might be “yay, extensions finally work the way I always wanted them to”.

Cheers,
Matthew

···

On Apr 5, 2017, at 7:11 PM, Colin Barrett via swift-evolution <swift-evolution@swift.org> wrote:
On Mon, Apr 3, 2017 at 2:35 PM Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Cheers,
-Colin

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

I'm broadly in favor of this.

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

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 :P (This is why we write proofs!)

This is a very interesting perspective Colin. This idea seems to align well with the intent for extensions that Chris stated earlier. This way of thinking about it does make the proposal much cleaner conceptually. If we’re going to adopt this perspective I think we should go all the way - same file extensions really should be inline semantically. This means same file extensions would also have the ability to include stored properties which is something many people have asked for.

I wonder how David and the core team would feel about modifying the proposal to adopt this “inline same file extensions" perspective.

I like the idea :blush: I have small reserves as to the confusion it could cause new users to understand the semantic differences between the two "kind" of extensions (same file and seperate file)

···

On 6 Apr 2017, at 03:34, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 5, 2017, at 7:11 PM, Colin Barrett via swift-evolution <swift-evolution@swift.org> wrote:

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

IMO this motivates the proposal better by acknowledging that most developers in the community use same file extensions for purely organization purposes. The implicit desire is that they be transparent boundaries that carry no semantic weight at all. I think a proposal with this kind of motivation is more likely to be well received by the broader community than a change that is only focused on access control in a very specific context. Instead of “why do they keep changing access control” the response might be “yay, extensions finally work the way I always wanted them to”.

Cheers,
Matthew

Cheers,
-Colin

Thoughts? Volunteer?

  - Doug
_______________________________________________
swift-evolution mailing list
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

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

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.]

Thank you for sharing your opinion regarding this subject.
Do I understand correctly, that *you* propose to just revert access levels and modifiers to Swift2 stage? (i.e. to drop current 'scoped-private' and rename 'fileprivate'->'private')
Or do you support to leave current 'scoped-private' under another name?

Vladimir.

···

On 06.04.2017 20:41, Jordan Rose via swift-evolution wrote:

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.

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

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)

I don’t get that impression. Even with this proposal, fileprivate is readily available to share implementation details with other types in the file. I view this proposal’s version of private very similarly to private in other languages (extensions in the same file as the type feel like part of the type’s scope to me).

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 don’t feel like this proposal reduces the usefulness of fileprivate, it just makes private more attractive more most cases (i.e., it’s not because public is a good soft-default that open is any less useful).

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.

Speaking for someone who uses extensions extensively, I’ve found very little use for private in my own code.

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?

If it’s the right tool for the job, then the goal of SE-0025 to make private the soft-default and file private used in rarer occasions have failed. And that’s how I see this proposal: as trying to fix this original goal.

···

On 6 Apr 2017, at 19:41, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

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.

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

-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.

I don’t know what you mean by strong in strong-scoped access, but your statement seems false. It does not remove the scoped access control, it only relaxes it in extensions to types in the same file.

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.

The name of fileprivate is not reason for this proposal. fileprivate has an awkward name precisely because it was planned for it to be used less often. This proposal’s goal is to make private more attractive to fulfil that original goal. fileprivate’s awkwardness is good, because it attracts attention to it when it is used.

···

On 7 Apr 2017, at 15:41, BJ Homer via swift-evolution <swift-evolution@swift.org> wrote:

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 <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&gt;, 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&gt;, 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

The problem I see with that is that it would introduce orthogonal access levels whereas they have all been hierarchal in nature up to now.

Right. That was the motivation for “private” being restricted to extensions/definitions in the same source file.

  - Doug

···

On Apr 3, 2017, at 12:50 PM, David Hart <david@hartbit.com> wrote:

On 3 Apr 2017, at 21:36, Charles Srstka <cocoadev@charlessoft.com <mailto:cocoadev@charlessoft.com>> wrote:

On Apr 3, 2017, at 2:28 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto: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?

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

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.

We don’t have to make a change in Swift 4. If there’s a change that can resolve this issue, great…

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.

… but if not, then let’s shelve access control changes until some time when we can considered it holistically with something like submodules, as you note above.

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

The core team felt strongly that we couldn’t change these keywords. Source stability is important to Swift 4, and “don’t break source compatibility so much” is one of the top requests we hear from Swift developers, much more so than requests for specific new language features.

and certainly much less than the frustration over the suggested semantic change.

This isn’t clear to me. There could certainly be frustration over the suggested semantic change, for a number of reasons:

* It’s not as “tight” a meaning of private as the current scope-based private.
* It means we have a hybrid type-based/scope-based model.
* It’s the third meaning of ‘private’ in three years.

However, it is unlikely to break code (one would need to construct an ambiguity between two private declarations in different extensions of the same type in the same file), and causes zero code churn, because it’s widening the meaning of “private”, not changing it.

  - Doug

···

On Apr 3, 2017, at 1:13 PM, Matthew Johnson <matthew@anandabits.com> wrote:

On Apr 3, 2017, at 2:55 PM, Daniel Duan via swift-evolution <swift-evolution@swift.org <mailto: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&gt;, 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&gt;, 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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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.

We don’t have to make a change in Swift 4. If there’s a change that can resolve this issue, great…

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.

… but if not, then let’s shelve access control changes until some time when we can considered it holistically with something like submodules, as you note above.

This is certainly what I would prefer. I only mention renaming because there is such strong interest in changing something. I would be happy to defer this topic and have been arguing for that approach ever since your note that only SE-0159 would be considered in scope for Swift 4.

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

The core team felt strongly that we couldn’t change these keywords. Source stability is important to Swift 4, and “don’t break source compatibility so much” is one of the top requests we hear from Swift developers, much more so than requests for specific new language features.

That’s fair.

and certainly much less than the frustration over the suggested semantic change.

This isn’t clear to me. There could certainly be frustration over the suggested semantic change, for a number of reasons:

* It’s not as “tight” a meaning of private as the current scope-based private.
* It means we have a hybrid type-based/scope-based model.
* It’s the third meaning of ‘private’ in three years.

However, it is unlikely to break code (one would need to construct an ambiguity between two private declarations in different extensions of the same type in the same file), and causes zero code churn, because it’s widening the meaning of “private”, not changing it.

I’m speculating based on my read of the community here as well as other Swift developers I know. I could be wrong, but my sense is that the items you list would cause more frustration than renaming, especially if the name change purged `fileprivate`. I don’t know anyone outside the evolution community who I think would complain if access control was left alone for a while. Some were not happy with the changes in Swift 3 but I don’t hear too much about it off the list anymore now that the migration is over and people have adapted.

···

On Apr 3, 2017, at 3:54 PM, Douglas Gregor <dgregor@apple.com> wrote:

On Apr 3, 2017, at 1:13 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

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

  - Doug

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&gt;, 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&gt;, 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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution