Type-based ‘private’ access within a file

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.

You mean a namespace? Ask some greybeard C++ developers how that one
worked out.

Honestly, regardless of names, I see the following needs:

1. Keep your mitts off this code, this is for me alone. You will break
things if you change this.
2. This one is for me and my relatives who know what we're doing with it.
3. This is for my group as we work together on this problem.
4. This is for anyone that wants us to solve this problem for them.
5. This is for anyone that wants to try to solve this problem some other
way.

(private, protected, internal, public, open — perhaps?)

What we call them matters little, as long as none of those names are
fileprivate. :slightly_smiling_face: File-based access control is so very ‘70s (and this is
coming from someone who has used C for a Very Long Time and loves it more
than Swift, honestly). For *this* language, it’s the wrong tool. We have
those new-fangled hierarchical types and extensions all in those fancy
little modules, so let’s use them as the people expect them to be used.

When submodules are A Thing, revisit them in terms of the “definitions"
above and see where things fit. If we — heaven forbid — think we need an
additional “export” keyword then we’ll have that firefight

Yeah basically my main objection to this proposed change and my general
dislike with current access controls is that they continue to depend on
file level scoping to provide for a functionality like "protected" in C++
(not that I exactly want that either, at least not friend). This forces you
to organize things in certain ways if you want to do anything more then
internal module level access.

I don't like the proposal primarily because it conflates file scope and
private scope which I think makes things more confusing and builds more on
the "crutch" of a file construct for access control. I much rather keep
things clear and explicit by requiring the use of fileprivate for those
situations instead of muddling up private (at least for now).

Instead I would want a protected like thing to be looked at that would
replace the need for fileprivate and that should be looked at in
conjunction with sub modules and likely properties, etc. ...let's spend out
energy on breaking away from file based access control. (that would make
playground better as well)

I feel most of the access controls levels in swift are well setup for
progressive disclosure... internal by default it great, you can get to work
without needing to know access controls. You can start to learn it by
putting your code in modules and dealing with public (and sometimes open)
which is great first way to understand the what and why of wanting to
control access to things. You can then start to learn about inter-module
encapsulation using private and then fileprivate.

-Shawn

···

On Mon, Apr 3, 2017 at 8:38 PM Adam Knight via swift-evolution < swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 8:11 PM, Nevin Brackett-Rozinsky 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.

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

I’m curious to know why you state this, you seem to agree with it below.

Granted: there will be less need for `fileprivate` with this.

Right, glad to hear that you agree it will become more rare.

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

Agreed on both points.

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.

Right. That’s the part that makes fileprivate more meaningful. This was exactly the *purpose* of having fileprivate in the first place. We want to enable this sort of sharing of private implementation details, but we want to make it explicit at the point of declaration when something like that is going on.

Thanks for jumping in to this thread Chris! It’s always interesting to hear your perspective.

This makes sharing across types within the file more explicit, but it also makes state that should be tightly encapsulated less explicit unless you create a wrapper type for that state.

One pattern I have used to good effect is placing this kind of state and the basis operations that manipulate it inside the type declaration and placing operations defined in terms of the basis operations in extensions on the type in the same file. This pattern no longer works as intended under this proposal. In order to migrate code written this way it is necessary to introduce a new type that encapsulates the state and provides the basis operations. This would obviously be a manual migration. I don’t know how many people have adopted styles in Swift 3 that will require manual migration to preserve semantics but it is greater than zero. This is churn that matters and shouldn’t be ignored.

I suppose a reasonable argument can be made that requiring encapsulation of this kind of state in its own type is a good pattern to that should be encouraged. It certainly calls more attention than the distinction between `private` and `fileprivate` by requiring some boilerplate. The current proposal makes sense to me if you assume that this pattern is worth the boilerplate because it really stands out. It means we encourage the “right” pattern (again, if you agree this pattern is good) and it means we also call special attention to cross-type sharing via `fileprivate` (because as you note it will be more rarely used).

On the other hand, if you disagree with the argument that we should have to create a new type for this kind of encapsulation then most important question becomes whether it is more important to highlight cross-type sharing within the file or have the convenience of encapsulating fragile state and highlighting it as such without the need to create a new type. IMO highlighting and tightly encapsulating fragile state is a more important concern.

Do we (the community and the core team) want to encourage programmers to create new types when this kind of encapsulation is needed rather than requiring on lexically scoped access control (that does not cross same-file, same-type extension boundaries)? If yes, then do we think encouraging this and gaining the benefit of highlighting same-file, cross-type interactions are big enough benefits to offset the “hybrid” (type and scope) access control model and another change to the meaning of `private`?

I like the elegance of a purely scope-based access control model and the tight encapsulation of lexically scoped access control but I can also see some merit in the arguments for this change. I’m interested in hearing any reactions to the lines of reasoning for and against the proposal I have outlined above.

···

On Apr 5, 2017, at 10:30 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Apr 5, 2017, at 5:13 AM, Michel Fortin <michel.fortin@michelf.ca <mailto:michel.fortin@michelf.ca>> wrote:

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

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

Again, this is about progressive level of disclosure. It looks like our QoI isn’t good enough right now, but the expected flow is that you write the invalid code (silly example here):

struct MyType {
  private var innards : T
}

extension String {
  func myHelper(x : MyType) {
     use(x.innards)
  }
}

You get the standard “innards is inaccessible due to private protection level” error message, but that message should have a note w/FixIt attached to it, offering to upgrade innards to fileprivate.

This approach is exactly why most people won’t have to care about it … until they need it. At which point, the compiler provides an automatic onramp for them.

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

We don’t want to discourage them, we want to make them more explicit. This was the intent of SE-0025, and I think the intent was good.

-Chris

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

Ok to be clear. I do not support changing private the way outlined in this
proposal nor do I support reverting to swift 2 style. I do not want to
paint us further into the corner on depending on file based access control.
So if not other options remain on the table then in my opinion stay with
what we have at this point. It is clear and explicit with wording that make
some unhappy but gives the most folks tools that they want. (still
depending of file constructs which I don't like but so be it...)

If submodules are on the table in the future ... then something like the
following makes a lot on sense to me: We have the migrator change
"fileprivate" to "private" and make this "private" mean accessible by the
current submodule (currently defined to be in current file). We have the
migrator change "private" to "scope[d]" keeping the current meaning of
private. Then work on something like a submodules concept that allows
subscoping inside of a module and/or enhance private (newly named private)
to work across files for those things that make sense (subclasses,
extensions, etc.).

-Shawn

···

On Wed, Apr 5, 2017 at 6:53 AM David Hart <david@hartbit.com> wrote:

On 5 Apr 2017, at 13:51, Shawn Erickson via swift-evolution < > swift-evolution@swift.org> wrote:

On Wed, Apr 5, 2017 at 4:31 AM Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

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

Now that is a change I would 100% support when factoring in sub modules. I
would support that even before submodules come around but would prefer it
to wait for submodules.

But the core team said there will not come back on their decision. We
should discuss what can be done instead, not repeat the same arguments and
opinions which bring us nowhere.

If our goal was to duplicate what Objective-C could do but without header files, we would essentially have:

* `public`
* `internal`
* `semiprivate`
* `fileprivate`

Symbols in `semiprivate` scope would be visible to the file they were in as well as any file that explicitly asked for access to `semiprivate` symbols in that file. (In practice, I think we'd probably tie `semiprivate` to submodules, not to files, though submodule membership might not have a granularity below full files.)

There would be no scoped `private` or `typeprivate` or anything of the sort. That just isn't a thing that existed in Objective-C. So I'm not sure why you're invoking Objective-C to argue that we need a type-based private.

···

On Apr 5, 2017, at 2:27 PM, Tony Arnold via swift-evolution <swift-evolution@swift.org> wrote:

I know Swift has different purposes for different people here, but ultimately it’s supposed to support great application development for Apple’s platforms, right? To my eyes, `fileprivate` should never have been introduced without some kind of `typeprivate` (similar to how things would be declared back in Objective-C land with a `*+Private.h` header that you could import when it was needed). Right now, there’s no way to duplicate that pattern in Swift - I would need to make anything I wish to access `internal` which exposes it to everything within the application/module - surprisingly, this is a regression from the tooling and access levels I had available in Objective-C.

--
Brent Royal-Gordon
Architechies

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.

This is the part of all of these conversations that concerns me deeply. Is the assumption that it is now “best practice” to place all shared implementation into a single file? Aren’t those files going to become quite large in real world use? That’s a terrible thing to encourage!

It depends on what these access control levels mean to the developers, not just on how they affect the compiler or symbol exposure.

For instance, my viewpoint is that private is for hiding implementation details of a type that someone editing elsewhere within the same module shouldn’t need to understand to do their job correctly. That means all unsafe details, and safe implementation details to be hidden to decrease coupling.

Fileprivate is used when unsafe details are needed to share implementation details outside a type with other types or free functions, by embedding all the accesses into a single file. Today, it also used to expose safe and unsafe details to extensions of the type within the same file.

Don't fall into the trap of just always using the lowest acceptable level of access control, rather than choosing levels below “internal” to reduce coupling of implementation details and preventing unsafe access to a type. If you focus on using the lowest acceptable access control level, you’ll wind up structuring your code around reducing said access controls - which will indeed result in all the code getting thrown into a single file ;-)

My experience working with protocol conformances in Objective-C over the years is that breaking protocol conformances into categories/extensions on the original type *in separate files* is the best way to keep things small, testable and focused.

Separating protocol conformances into separate files, whilst still being able to access private members of the extended type promotes smaller files, and more focused implementation within those files.

Based on the above, I’d say my viewpoint is:
- If your extension is based on details that don’t require knowledge of the internal workings of the type, then you should be able to expose those details of the type to the module, and author the protocol conformance in any file you like. All third party conformances of your type to a protocol are necessarily of this type, because they don’t have internal knowledge or access.

- If your extension requires internal knowledge of the type, it should be consolidated into a single file with the type so that changes to the internals are localized (and also promotes higher cohesion of your code). Implementing Encodable/Decodable are likeliy examples of this.

- there is a grey area where there are details which are safe but that you don’t really want to expose due to implementation details, or could be potentially be written better with implementation detail access. Then you have a trade-off to decide one way or another. Implementing CustomDebugStringConvertible or Equatable might be examples of this.

I know Swift has different purposes for different people here, but ultimately it’s supposed to support great application development for Apple’s platforms, right? To my eyes, `fileprivate` should never have been introduced without some kind of `typeprivate` (similar to how things would be declared back in Objective-C land with a `*+Private.h` header that you could import when it was needed). Right now, there’s no way to duplicate that pattern in Swift - I would need to make anything I wish to access `internal` which exposes it to everything within the application/module - surprisingly, this is a regression from the tooling and access levels I had available in Objective-C.

I personally fought against the inclusion of scoped private originally because I feel that it was sufficient that developers have to understand the code that they are working on - they need to understand the public details of dependent modules, the internal and public details of the module they are working on, and all the details of the file they are working in. I didn’t see the need to go smaller than file, to say they have to understand the file private details of the file they are in and the private details of the type they are editing. But c'est la vie.

The use of a type scoped private independent of a same file restriction would be to spread implementation details on a type across multiple files, which could be argued to be a bad practice. If nothing else, it means a developer can work around your attempt to encapsulate and hide implementation details by creating accessor methods in an extension elsewhere in the codebase, and that this would not be revealed until something broke.

-DW

···

On Apr 5, 2017, at 3:27 PM, Tony Arnold via swift-evolution <swift-evolution@swift.org> wrote:

On 6 Apr 2017, at 02:54, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org> wrote:

Because while it was technically possible for any file that wanted to to include the private header, in *practice* this was often used to implement ‘typeprivate’-like functionality.

Charles

···

On Apr 5, 2017, at 6:10 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 5, 2017, at 2:27 PM, Tony Arnold via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I know Swift has different purposes for different people here, but ultimately it’s supposed to support great application development for Apple’s platforms, right? To my eyes, `fileprivate` should never have been introduced without some kind of `typeprivate` (similar to how things would be declared back in Objective-C land with a `*+Private.h` header that you could import when it was needed). Right now, there’s no way to duplicate that pattern in Swift - I would need to make anything I wish to access `internal` which exposes it to everything within the application/module - surprisingly, this is a regression from the tooling and access levels I had available in Objective-C.

If our goal was to duplicate what Objective-C could do but without header files, we would essentially have:

* `public`
* `internal`
* `semiprivate`
* `fileprivate`

Symbols in `semiprivate` scope would be visible to the file they were in as well as any file that explicitly asked for access to `semiprivate` symbols in that file. (In practice, I think we'd probably tie `semiprivate` to submodules, not to files, though submodule membership might not have a granularity below full files.)

There would be no scoped `private` or `typeprivate` or anything of the sort. That just isn't a thing that existed in Objective-C. So I'm not sure why you're invoking Objective-C to argue that we need a type-based private.

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

I’m curious to know why you state this, you seem to agree with it below.

To clarify: I agree there would be less need for `fileprivate`. I just don't think it'll be that much less that it'll qualify as rare.

Perhaps we just don't have the same rarity threshold, or we are not looking at the same kind of code. "Rare" is a rather subjective measurement.

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.

Right. That’s the part that makes fileprivate more meaningful. This was exactly the *purpose* of having fileprivate in the first place. We want to enable this sort of sharing of private implementation details, but we want to make it explicit at the point of declaration when something like that is going on.

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

Again, this is about progressive level of disclosure. It looks like our QoI isn’t good enough right now, but the expected flow is that you write the invalid code (silly example here):

struct MyType {
  private var innards : T
}

extension String {
  func myHelper(x : MyType) {
     use(x.innards)
  }
}

You get the standard “innards is inaccessible due to private protection level” error message, but that message should have a note w/FixIt attached to it, offering to upgrade innards to fileprivate.

This approach is exactly why most people won’t have to care about it … until they need it. At which point, the compiler provides an automatic onramp for them.

If that fixit only shows up rarely, and if people always take its suggestion to fix the access level of the declaration when it appears, wouldn't that signify the distinction between the two access levels is not very meaningful in the first place?

The only way I see `private` having real meaning is if someone teaches himself to write `fileprivate` by default instead of `private`. Then when the compiler complains about something being `private` he will know he is accessing something that was *intentionally* locked under a stricter access level, making him think about what he is doing before changing it. Whereas with everything under a stricter access level than necessary by default, relaxing access levels becomes a normal thing to do and the stricter access level doesn't offer much protection anymore.

The sole mistake with SE-0025 in my opinion was to make `private` something people would use by default instead of `fileprivate`. The language should make people explicitly choose the stricter access level when useful instead of making it the default choice. That would have given real meaning to that choice. That would have made relaxing an access level something worth some scrutiny.

Right now we have the total opposite to scrutiny: we want to see the strict access level relaxed almost automatically with a Fixit as soon as it becomes a hindrance. It's only considered a good thing because everybody knows most `private` declarations are perfectly fine being `fileprivate`. It's unfortunate that the few declarations that really need to stay `private` will risk the same Fixit treatment without anybody noticing.

Seems like I'm ranting about something that's already decided now. So I'll stop and return to more productive things.

···

Le 5 avr. 2017 à 11:30, Chris Lattner <clattner@nondot.org> a écrit :
On Apr 5, 2017, at 5:13 AM, Michel Fortin <michel.fortin@michelf.ca <mailto:michel.fortin@michelf.ca>> wrote:

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

--
Michel Fortin
https://michelf.ca

Hi Brent,

···

On 6 Apr 2017, at 09:10, Brent Royal-Gordon <brent@architechies.com> wrote:

So I'm not sure why you're invoking Objective-C to argue that we need a type-based private.

I’m not trying to invoke the ghost of Apple-languages past, seriously :)

I was outlining a use-case of something that I could do under Objective-C (and used regularly), and how type-based private (within the same submodule, sure) might be a better answer to that same problem.

I’m sorry, I realise I’ve derailed my part of this conversation into a feature request — I’m trying to express that my experience over the past year is that only having private/fileprivate is making it more difficult to maintain some of the larger apps that I work on (the file lengths are getting quite long for common scenarios I could handle more gracefully in the past).

Reading that after Swift 4, this will never change has also made me seriously uncomfortable given how much conflicted conversation has occurred on this topic. To me, it sounds like there is a need to address some of the intermediary access levels before this gets locked down permanently, but I’m also just an app developer - I don’t have a rounded Comp Sci understanding of many of the topics being discussed.

I’ve had my (rambling, slightly grammatically incorrect) say now, thanks for listening.

-t

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

ABN: 14831833541

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

The idea of a private member is that it’s only visible within the class that declares it. In languages where the class is traditionally declared all at once, that’s straightforward enough; however, the tradition of implementing swift classes as a series of extensions (currently) forces opening much more than should be to any other classes within the file. If class B needs access to one private within class A, it also gets access to every single variable used by an extension to A, and every single function used by an extension outside the one it’s declared in. That’s way more visibility into the class than it should have.

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.

IMO having a free function access the internals of an object is a huge code smell. It should almost always be a function on the object or the class. And I’d be highly skeptical of any architecture that requires one class to access another class’s privates directly. In general, I’m fairly strongly opposed to having multiple externally accessible classes in the same file (probably influenced by having used Java through most of my education).

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

Well, yes, that’s what I’d expect and want, and that’s the whole point of access levels. If I have a private member and want to use it in another class, I should have to make a conscious decision about whether to open up that member, add an externally visible one, or just do it a different way entirely. (One might argue based on that point that the fix-it to widen the access level is actually harmful.) I’m not sure what your point is here, but I think forcing the dev to stop and think about whether the access needs to be loosened is a *good* thing.

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?”

Again I’m not seeing your point. Yes, you should think twice about why it’s in the same file. Yes, there is harm because it can now see fileprivate members that it shouldn’t.

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.

Are you arguing for reverting to the Swift 2 definition of private = modern fileprivate?

I’d argue exposing privates to everything in a file actually *increases* cognitive load because now I have to keep track of which classes are declared in the same file. If private has a sane meaning (initial declaration + “primary” extensions, the level under consideration here) only the class I know I’m working in has access. Much simpler and context-free.

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

No, I’d say 99+% of the time that I have to make something fileprivate, it’s only for the benefit of same-file extensions, and the proposal we’re considering here would negate most of the need for that. Exposing those members to anything else that happens to be in the same file is an unfortunate failing of Swift’s access control. Given Swift’s emphasis on extension-based implementations, I expect many others are in the same boat.

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.

Unfortunately, for the most part you can’t really do that properly without allowing stored properties in extensions anyway, because either the variable(s) involved have to be fileprivate or the methods have to go in the primary definition. Either way, more things can access the state than should.

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?

Because it’s more broad than needed. Everything that should be restricted to the type but is declared in or used by an extension has to be fileprivate, exposing its private parts to every other class in the file. Extending `private` to cover same-file extensions lets classes at least put on some underwear.

···

On Apr 5, 2017, at 6:54 PM, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Wed, Apr 5, 2017 at 12:02 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Nevin
_______________________________________________
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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

Questions:

1. does this mean no changes like this will happen to Swift 5?
2. can core team provide any discussions/thoughts that they had about submodules, for a “future consideration” section in this proposal?

···

On Apr 3, 2017, at 2:22 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 5:21 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

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

On 3 Apr 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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:

John.

John.

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

_______________________________________________
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

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

If that's the case, I don't think we should change the definition of `private` to something so unproven, and which violates our access control design's principles so much, right before the deadline. We do at least know that scoped `private` has some uses; we have no idea if file-and-type `private` will, but we *do* know it will eliminate many of the uses we've found for `private` (like ensuring that only a limited set of methods can use a property with tight invariants.)

It’s not necessarily unproven. It’s actually much closer to what private in other languages look like (with Swift extensions in the mix).

Sure, but extensions are precisely the reason why `private` is complicated in Swift. That's a bit like saying "we should use integer string indices because they work just fine in languages without good Unicode support".

And it would still allow many uses of private, like Drew Crawford’s ThreadsafeWrapper example from the 23rd of March.

That's great, but the goal is not "Don't break Drew Crawford's one example from the review thread". The goal is "provide a set of access levels which provide appropriate degrees of protection for many use cases".

To talk about concrete examples, here's a SortedDictionary type I wrote: <https://gist.github.com/brentdax/106a6a80b745bd25406ede7a6becfa30&gt; It has a pair of `private` properties called `_keys` and `_values`, whose indices have to stay in sync. To enforce that invariant, it uses `private` to ensure that only a few primitive members have direct access to the properties in question. Changing `private` to be file-and-type-based would render that protection useless.

Now, I could redesign this to wrap `_keys` and `_values` plus the privileged members in a separate type, but that type would be wholly artificial; it would have no meaning of its own, and would exist solely to get a certain access control behavior. One effect would be that I'd have to write the `startIndex` and `endIndex` properties twice, increasing boilerplate for no good reason. This is one of those places where scoped `private` really *is* just what I want, and type-and-file `private` really, really isn't.

I also think that allowing stored properties in same-file/same-module extensions will significantly improve the usefulness of `private` and reduce the need to have a same-type-same-file `private`. Right now, the fact that `private` properties can only be used from the main declaration requires that all types using `private` state be stuffed into that declaration. But it doesn't have to be that way, and once it is, `private` won't feel quite so restrictive.

I think that would not help. We would still be constantly juggling between private and fileprivate depending if we are trying to access a property in the same scope or not. When writing types as a minimal internal interface followed by a set of grouping and conformance extensions, you would still constantly bump against limitations of private and resort to fileprivate.

I look at this the opposite way: If you do not sometimes have to switch a `private` to `fileprivate` or vice versa, then `private` and `fileprivate` are basically synonyms and we ought to accept SE-0159 just to simplify the language. If, in your chosen coding style, `private` and `fileprivate` are almost always synonyms, then it's a distinction without a difference, cognitive load that doesn't bring any benefit.

IMHO, the "I have to switch back and forth" argument is a good reason not to have two different sub-file access levels because it suggests that the distinction being made is too fine. It's not a good reason to loosen one of the sub-file access levels so it looks more like the other, which only makes the distinction even finer.

(Besides, since we currently can't have two different `private` symbols on the same type in the same file, making this change later would be source-compatible except for overload resolution. We can open that box any time we want, but once we do, we can't close it again.)

John McCall stated this is the last opportunity to improve the status-quo:

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

And I'm pushing back on that, because there is no technical reason I can discern why we can't go from scoped `private` to file-and-type `private`. Perhaps there's a social reason—the core team won't want to change access control semantics once Swift is more stable and popular, or they think this topic is a giant ongoing distraction and want to settle it once and for all so they can declare it off-limits forever—but I don't think we should make a speculative change to yet a third design right before we do that.

Honestly, I think it's becoming increasingly clear that no access control design will ever satisfy everybody. So let's lock down the unsatisfactory design we know, rather than the unsatisfactory design we don't.

···

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

On 3 Apr 2017, at 23:55, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

--
Brent Royal-Gordon
Architechies

And having:

1. open
2. public
3. internal
4. Whatever your new "internal but type-only" access level would be called
5. fileprivate
6. private

Is *not* overcomplicated? At that point, it's much simpler to think of it as four access levels + type-only or all-types.

Again, I'm not saying such a design is *good*. I'm saying it's *better than six access levels*.

···

On Apr 3, 2017, at 3:51 PM, Vladimir.S <svabox@gmail.com> wrote:

Moreover, I think that we need *additional* access level(to current
'private'), which will mean 'can be accessed from extensions and subtypes
in the same *module*' to be able to split type's conformances to number
of files and don't make implementation details accessible&visible for
whole module. (there was 'extensible' modifier discussed previously).

If we wanted to do this, I think we'd want a `protected` modifier that was
orthogonal to `internal` and `private` (which would probably revert to
`fileprivate` semantics):

I don't think so, IMO it seems like over-complicated structure of access levels.

--
Brent Royal-Gordon
Architechies

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

John.

···

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

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

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

On 3 Apr 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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:

John.

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

_______________________________________________
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

This is very disappointing. We can’t realistically get access controls correct until we have a story around submodules, etc. Those things are out of scope for Swift 4, and we can’t change access controls after Swift 4. Catch-22.

We should hold off on doing anything now, and redesign holistically when we do the rest.

-1. This just adds tires to the tire fire. I feel like it only adds to the confusion between private and fileprivate by making them less distinct from one another. If we have to make a change now (because we won’t be able to later… which I would strongly ask you to reconsider), then I would go with the renaming proposal. It is not at all ideal, but it would at least make things a little better long-term if we are to be stuck with the design.

I regret pretty much all of the proposals in Swift 3 which were accepted based on “We have to do this now. or else…” Pretty much universally, it would have been better to wait.

···

On Apr 3, 2017, at 2:22 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 5:21 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

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

On 3 Apr 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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:

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

John.

John.

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

_______________________________________________
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

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

I agree with every point up to, but excluding, this conclusion. A broken
language will remain broken forever.

Zachary Waldowski

zach@waldowski.me

···

On Mon, Apr 3, 2017, at 07:55 PM, Brent Royal-Gordon via swift-evolution wrote:

Honestly, I think it's becoming increasingly clear that no access
control design will ever satisfy everybody. So let's lock down the
unsatisfactory design we know, rather than the unsatisfactory design
we don't.

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

Questions:

1. does this mean no changes like this will happen to Swift 5?

I think it is likely that we will not accept any proposals that change the basic rules of existing language features, no, unless it's a very serious problem or a very minor change.

2. can core team provide any discussions/thoughts that they had about submodules, for a “future consideration” section in this proposal?

We have not had any serious conversations about submodules.

John.

···

On Apr 3, 2017, at 5:32 PM, Daniel Duan <daniel@duan.org> wrote:

On Apr 3, 2017, at 2:22 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 3, 2017, at 5:21 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

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

On 3 Apr 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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:

John.

John.

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

_______________________________________________
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

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

This is very disappointing. We can’t realistically get access controls correct until we have a story around submodules, etc. Those things are out of scope for Swift 4, and we can’t change access controls after Swift 4. Catch-22.

We should hold off on doing anything now, and redesign holistically when we do the rest.

I'm not sure what sort of holistic redesign you're imagining.

John.

···

On Apr 3, 2017, at 9:16 PM, Jonathan Hull <jhull@gbis.com> wrote:

-1. This just adds tires to the tire fire. I feel like it only adds to the confusion between private and fileprivate by making them less distinct from one another. If we have to make a change now (because we won’t be able to later… which I would strongly ask you to reconsider), then I would go with the renaming proposal. It is not at all ideal, but it would at least make things a little better long-term if we are to be stuck with the design.

I regret pretty much all of the proposals in Swift 3 which were accepted based on “We have to do this now. or else…” Pretty much universally, it would have been better to wait.

On Apr 3, 2017, at 2:22 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 3, 2017, at 5:21 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

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

On 3 Apr 2017, at 22:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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:

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

John.

John.

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

_______________________________________________
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

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

+1

···

Sent from my iPhone

On 3 Apr 2017, at 22:21, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com> wrote:

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

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

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> wrote:

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

John.

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 11:34 AM, 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

_______________________________________________
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

This is very disappointing. We can’t realistically get access controls correct until we have a story around submodules, etc. Those things are out of scope for Swift 4, and we can’t change access controls after Swift 4. Catch-22.

We should hold off on doing anything now, and redesign holistically when we do the rest.

-1. This just adds tires to the tire fire. I feel like it only adds to the confusion between private and fileprivate by making them less distinct from one another. If we have to make a change now (because we won’t be able to later… which I would strongly ask you to reconsider), then I would go with the renaming proposal. It is not at all ideal, but it would at least make things a little better long-term if we are to be stuck with the design.

I actually think this good slight enhancement to private makes sense and brings it in line with many requests we have gotten during our earlier discussion. I think that we are making a mountain out of a molehill by pushing back against this as if it would rush submodules or a holistic design sooner... Also, it is a minor non source breaking extension, not something huge and potentially damaging to the language.

···

Sent from my iPhone

On 4 Apr 2017, at 02:16, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

I regret pretty much all of the proposals in Swift 3 which were accepted based on “We have to do this now. or else…” Pretty much universally, it would have been better to wait.

On Apr 3, 2017, at 2:22 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

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

On 3 Apr 2017, at 23:19, John McCall <rjmccall@apple.com> wrote:

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

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

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> wrote:

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…

I still think this is a worthwhile goals.

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.

Won’t making big modifications later be even more problematic than now, in the name of source stability?

Yes. Big changes along these lines will not be considered later. At best, it would be possible to "re-cast" existing behaviors in light of new features — that is, significantly changing *how we talk about those behaviors*, and changing how we understand them in the broader language, but not actually changing the behaviors themselves.

That’s why I don’t buy the “lets postpone this discussion to a future submodule design” argument. Let’s get this in a reasonable state now :)

I agree. This is why we asked swift-evolution to consider this last tweak: it is realistically the last opportunity to do it.

John.

John.

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 11:34 AM, 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

_______________________________________________
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

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

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.

You mean a namespace? Ask some greybeard C++ developers how that one worked out.

Honestly, regardless of names, I see the following needs:

1. Keep your mitts off this code, this is for me alone. You will break things if you change this.
2. This one is for me and my relatives who know what we're doing with it.
3. This is for my group as we work together on this problem.
4. This is for anyone that wants us to solve this problem for them.
5. This is for anyone that wants to try to solve this problem some other way.

(private, protected, internal, public, open — perhaps?)

What we call them matters little, as long as none of those names are fileprivate. :slightly_smiling_face: File-based access control is so very ‘70s (and this is coming from someone who has used C for a Very Long Time and loves it more than Swift, honestly). For *this* language, it’s the wrong tool. We have those new-fangled hierarchical types and extensions all in those fancy little modules, so let’s use them as the people expect them to be used.

When submodules are A Thing, revisit them in terms of the “definitions" above and see where things fit. If we — heaven forbid — think we need an additional “export” keyword then we’ll have that firefight

Yeah basically my main objection to this proposed change and my general dislike with current access controls is that they continue to depend on file level scoping to provide for a functionality like "protected" in C++ (not that I exactly want that either, at least not friend). This forces you to organize things in certain ways if you want to do anything more then internal module level access.

Even if you don't like it, Swift's access control's reliance on file scoping is here to stay. It's too late to change that.

I don't like the proposal primarily because it conflates file scope and private scope which I think makes things more confusing and builds more on the "crutch" of a file construct for access control. I much rather keep things clear and explicit by requiring the use of fileprivate for those situations instead of muddling up private (at least for now).

It's true that it conflates lexical and file scope. That's it's one drawback.

Instead I would want a protected like thing to be looked at that would replace the need for fileprivate and that should be looked at in conjunction with sub modules and likely properties, etc. ...let's spend out energy on breaking away from file based access control. (that would make playground better as well)

Whatever we want, the core team has made it clear that access levels won't be changing as substantially as that from now on. That's the entire reason 0159 was rejected: to not break source compatibility with users of private & fileprivate. So how can we expect any major change in the future?

That's why the current type-based proposal is the only viable alternative we have to resolve the grievances 0159 brought forward now. There's no "later".

···

On 4 Apr 2017, at 17:26, Shawn Erickson via swift-evolution <swift-evolution@swift.org> wrote:

On Mon, Apr 3, 2017 at 8:38 PM Adam Knight via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 3, 2017, at 8:11 PM, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org> wrote:

I feel most of the access controls levels in swift are well setup for progressive disclosure... internal by default it great, you can get to work without needing to know access controls. You can start to learn it by putting your code in modules and dealing with public (and sometimes open) which is great first way to understand the what and why of wanting to control access to things. You can then start to learn about inter-module encapsulation using private and then fileprivate.

-Shawn

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