Enhancing access levels without breaking changes

(Ted van Gaalen) #1


(wrote a bit or two about this before)
For a moment, let's make the unlikely assumption that really no one has a problem
with changing the next Swift version, having lexical scope as the only scope mechanism. . .
which would be that each and every item is visible and accessible only inside the source level where it is declared,
unless of course revealed outwards with an access modifier.
(.e.g. protected, internal, public (private would be implicit))
Like it is in most other procedural/OOP languages.

Now, also assume that Swift has always been that way: lexical scope only.

Given this, as yet, hypothetical Swift environment, my questions are:
Would this be feasible in Swift?

E.g. does it constrain/conflict with current Swift language constructs/organisation ?
(you can reveal items to the outside scope with access modifiers)

Side effects, technical limitations?

Am I right in thinking that Swift would be a lot easier to work with if lexical scope had
been there from the very beginning?

If Swift 4 would be set to lexical scope only, could the source conversion be automated successfully?
E.g. by automatically adding the "internal" access modifier to all items that don't have an access modifier right now in Swift 3.x ?

If all this would be possible, it would of course be a very drastic change,
but what is it worth to finally get scope access right once and for all ? (imho)

The necessity of “private” or “fileprivate” keywords is by itself
a clear signal that the current access mechanism is wrong, I think.

Very interested in your opinion, thank you.



Date: Wed, 12 Apr 2017 07:30:04 +0200
From: David Hart <david@hartbit.com <mailto:david@hartbit.com>>
To: Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>>
Cc: swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
Subject: Re: [swift-evolution] Enhancing access levels without
  breaking changes
Message-ID: <DACD7DE1-6BC6-457A-BE4D-B074C7B39A8C@hartbit.com <mailto:DACD7DE1-6BC6-457A-BE4D-B074C7B39A8C@hartbit.com>>
Content-Type: text/plain; charset=utf-8

On 12 Apr 2017, at 07:16, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:

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

I understand what you are saying and I wouldn't be against relaxing that requirement (not talking for Chris here).

The model would change from "Types share scopes with their extensions in the same file the type was defined" to "Types and their extensions share the same scope in each file".

Oh, I had missed that somehow. I agree that that is a very strange rule. Do you know why it was proposed that way?

We had to take a stance and Chris seemed to prefer the rule that was proposed. I didn't press because I'm sure he has reasons for preferring it that way. But I have a preference for generalizing visibility to all extensions, even to those in a different file than the type.

To me, the reason for limiting it to a file is about predictability, the ability to locally reason about a type, and the need to define some boundary (for symbol visibility reasons). Saying that extensions to a type have access to private members if they are in the same module is just as arbitrary as limiting it to a single file, and a whole lot less useful from the “reasoning about a type” perspective.

I think you misunderstand. We were talking about two extensions of a type, in a different file from the type, to share private members between themselves.
Doug Gregor mentioned it during the PR process and we added an example to disallow it, but in hindsight, I think it should be allowed.
Expanding it beyond a module would require a ton of stuff to be exported that otherwise wouldn’t be, and would defeat a ton of optimization potential that we can’t accept.