Access control below public [not `protected`]

We've had this exact argument, to the letter, repeatedly. This has been considered in detail, and if you want the reasoning why a proposal for type based access will never be accepted by the core team then read the previous two threads on the matter. [1][2]

Please stop bringing it back up. If you notice the levels of vitriol this subject managed to produce last time, you'll see that I was hardly exaggerating when I said that the whole topic of access control was radioactive.

I have wanted to stay out of this thread but do have one small comment to offer. The model of strictly nested scopes is important not only because it is simple but also because retroactive extension is a core part of the Swift programming model. This applies every bit as much inside a module as it does across module boundaries.

Just as user code may extend String with context-specific operations, user code within a module may extend any internal type with context-specific operations. These extensions are not considered part of the implementation of the type and should not gain access to implementation details. Aside from the scope of their declaration, Swift does not make a distinction between extensions that are part of an implementation and those that are retroactively adding context-specific members.

The desire to break an implementation into several files that share internal implementation details not visible to the rest of the module is best addressed by submodules, not type-based access control. I know Adrian has asked people not to mention submodules but they are very relevant to this discussion.

10 Likes

Hi Matthew, sorry if something dragged you into this thread by force. Do you an opinion why we should keep private and fileprivate alive if we had submodules? To be honest it's almost like those exist only because we don't have submodules yet, at least the whole arguments against type-bound access control gives me that impression.

2 Likes

Submodules are heavier syntactically than private/fileprivate, and Swift likes to be only as syntactically heavy as necessary. I should think the current access modifiers would be used as a first pass, and then upgraded into submodules if they start to become unwieldy.

You are probably right that private exists largely as an historical compromise due to the lack of submodules. Had submodules existed from the start (or even been introduced in the Swift 3 timeframe) I think private would have continued to mean fileprivate to this day.

1 Like

lol, it was not by force. I just don't think this thread is a constructive use of the community's time given the history of the topic.

That entirely depends on the design of the submodule system. Perhaps submodules could be designed in a way that would allow us to deprecate fileprivate and perhaps not. Even if such a design is possible, it isn't clear to me that it should be a design priority for submodules. In any case, I don't think it's worth speculating about that right now as they are out of scope for Swift 5.

1 Like

I'm not trying to be pedantic, but then why are we speculating that submodules serve a better job rather then a type bound access control. This surely is confusing, at least to me. Even iniside a submodule a type bound access control would be very useful to not go crazy with submodule nesting.

IMO the primary purpose of submodules is to provide a unit of encapsulation that is larger than a file but smaller than the whole module. My primary point was that there are very good reasons that type-based access control is not a good fit for Swift and I wanted to highlight one in particular. I mentioned submodules because I think it is important everyone is aware that there are other ways to address the use cases you mention.

I've said what I came to this thread to say and don't plan to contribute further unless you have questions about my comments on retroactive extensions.

2 Likes

I have a rough draft of a proposal for submodules if you wanted to look at it, but it should probably go into it's own thread. It's largely inspired by the current caseless enum as namespace trick.

There were drafts of quite a few submodule designs and extensive discussion threads last year. A quick search of the forums for "submodule" will return many results for interested readers.

Feel free to kick off it in a new thread, I'll be there to help and contribute, but keep it sane since others consider the submodules topic similar radioactive as the topic of this thread here (not me though). ;-)

That's certainly true enough. That's why I didn't just post mine already. If anyone who's read the previous proposals asks then I'll post mine. Otherwise I won't bother.

Well nothing will happen if nobody will step up and do the first step. I wasn't afraid to put my hand to the fire with thread as I mentioned in the original post. This topic already gathered some attraction and I'm open minded to switch into a nice and diplomatic discussion about submodules. If a potential submodule thread would successed then this thread here at least achieved one positive thing, it pushed Swift forward into a better future.

Furthermore the changes I presented actually are completely orthogonal to submodules since the migration path is quite simple, which means such a change can potentially still be introduces later, because it's almost additive. (However I have no idea how this would affect ABI.) BUT as I already stated a couple of times, I wasn't expecting too much with this thread rather then a nice discussion, without some sparks from above though.

1 Like

The answer to your question is that it turns out to be hard to find the one bit you're looking for in the middle of a massive wall of text.

4 Likes

But it only gets massive if the type is to big. Instead of fitting size for the problem. I mean like a single "game" class instead of subclasses for different aspects.

Or perhaps does our view of what is massive differ - can you explain what it means for you?

1 Like

Here is a link to the original post I had there before Adrian asked me to edit it. Try to find the relevant bit in there, and you'll quickly see why it's a massive PITA.

Sorry Charles originally I thought it was more or less a sarcastic joke, and as I said in private I'd like to keep this thread sane. :) You could have used spoilers for that matter.

<details> 
  <summary>Question?</summary>
   Text
</details>

I apologize if I misinterpreted your post.

1 Like

Funny but how does that transfer to code? I never had files/modules above a thousand lines, what is easily navigable with any decent IDE. Is that massive in your eyes? I'm really trying to understand you point.

btw, only needed 3 secs to find the hidden sentence...

Here is an example of an overwhelming Swift file from the Swift repository which is not only hard to read but probably very hard to maintain. I'm sure there are other examples in the wild that are by far more complex and more massive. Aside the current file height already, it's quickly notable that it's not documented properly which is a different story on it's own in case of documentation coverage but this can add another 2-5k lines at least.

Oh come on, it's easy to think of examples. For instance: making a custom view object for macOS. Between the logic to generate the content you need, the logic to draw the content on the screen, the code to handle user input, implementations of all the NSResponder IBAction methods, and implementations of all the protocols you needā€”NSCoding, NSSecureCoding, NSUserInterfaceValidations, NSTextInputClient, NSDraggingSource, NSDraggingDestination, accessibility support, search bar support, delegates for any subviews that need them, probably a kajillion other things I'm forgettingā€”if you stuff that all in one file, it's going to be completely obnoxious.

I just tallied up the lines in my hex edit view class, and if they were all in one file, that file would be 3,912 lines long. Needless to say, if you're somehow writing applications that only need 1,000 lines for the entire module, I have to wonder what type of applications you're writingā€”even a simple calculator app is likely to need more than that.

I just spent a non-trivial amount of time breaking up a much-too-large source file that I was having the damndest time wrapping my head around, which was causing me to waste tons of time trying to track down bugs in it. Once it's broken down into manageable chunks, wow! It suddenly makes some sort of sense!

Well of course, because you already knew what exact wording to search for because I had to neuter the original joke. Adrian's reaction proves that it apparently wasn't even obvious that there was something in there at all ;-)

1 Like

Yeah, the standard library is a bit of a beast. That's only partially due to access control issues though. Another part of it is that, by nature, the types and protocols in the standard library have to be very general so they tend to implement more stuff than a user type would on it's own.

Binary/FixedWidthInteger is particularly tedious to implement, especially since I don't think anyone ever got around to adding the default non-mutating implementations of the math operators based on the mutating versions. Thankfully custom integer types are rare in real code. Usually, if you have to do it at all, it's just a generic wrapper type that forwards to an existing type.

1 Like