swift-stdlib-tool was open-sourced, a number of proposals were accepted, Swift releases have themes, and a new proposal for fixing access controls in Swift is now under review!
Hello, it’s Paul Hudson from Hacking with Swift again, and after four weeks you’re probably sick of seeing me here. So, I’ll cut to the chase and get out of your way — I wrote a book about Server-Side Swift, and I think you’d like it.
Every Swift developer who has migrated code bases from Swift 1.x to 2.x, or even the more tedious 2.x to 3.x knows the pain of migrating to new Swift versions. In this episode we cover the intricacies of source stability and source-breaking changes. What exactly is a source-breaking change? It’s not as straight-forward as you may think!
News and community
Ole Begemann wrote a post, Swift Releases Have Themes, about a thoughtful message from Swift Core Team member Ben Cohen. Ole thinks Ben’s message on swift-evolution deserves more attention, and I agree! It is a couple of weeks old, so sorry for missing this in last week’s issue! 😳 Ole quotes the entire message and provides some commentary. Definitely read this. It’s important for the community to be aware of and help pursue the themes of each Swift release.
Commits and pull requests
Manav Gabhawala (@manavgabhawala) opened a pull request that implements a robin hood algorithm for hash collisions in
Dictionary. It looks like this will improve performance and fix 3 SR issues, although we’re still waiting on benchmark results from the swift-ci bot.
The proposal was very well-received and is accepted with one modification: the ordering rules for existential types that involve
classtype will be removed.
The ordering rules were intended to improve code clarity by requiring that the
AnyObject) constraint come first -
AnyObject & Pwould be well-formed but
P & AnyObjectwould be an error—enforcing more uniformity for Swift code and echoing a similar restriction that already exists for class definitions, where the superclass must come first. However, the ability to compose typealiases complicated the ordering rules considerably, and - as noted by Matthew Johnson - don’t provide the guarantee that the class constraint will always be first. Therefore, the core team felt that the resulting ordering rules introduced more complexity than they provided clarity, and therefore do not belong in the language.
The feedback on the proposal was unfailingly positive. Accordingly, the proposal has been accepted without further modification.
The proposal is accepted with the following revisions:
upToNextMinorwill be capitalized.
upToNextMinor()will name the first parameter
.onlywill be removed, as it was duplicative versus
- We will have cases for
.revisionversion specifiers, but will not provide special package initializers with named parameters for these.
This proposal was generally supported, though it did require some discussion and minor revision, and some users are eager for future proposals adding new API not covered by this proposal.
Proposals in review
This proposal presents the problems that came with the the access level modifications in SE-0025 and proposes reverting to Swift 2 behaviour.
Since the release of Swift 3, the access level change of SE-0025 was met with dissatisfaction by a substantial proportion of the general Swift community. Those changes can be viewed as actively harmful, the new requirement for syntax/API changes.
privatekeyword is a “soft default” access modifier for restricting access within a file. Scoped access is not a good behavior for a “soft default” because it is extremely common to use several extensions within a file. A “soft default” (and therefore
private) should work well with this idiom. It is fair to say that changing the behavior of
privatesuch that it does not work well with extensions meets the criteria of actively harmful in the sense that it subtly encourages overuse of scoped access control and discourages the more reasonable default by giving it the awkward name
privatekeyword should be reverted back to its Swift 2 file-based meaning and the
fileprivatekeyword should be deprecated.
One can explicitly write
@objcon any Swift declaration that can be expressed in Objective-C. As a convenience, Swift also infers
@objcin a number of places to improve interoperability with Objective-C and eliminate boilerplate. This proposal scales back the inference of
@objcto only those cases where the declaration must be available to Objective-C to maintain semantic coherence of the model, e.g., when overriding an
@objcmethod or implementing a requirement of an
@objcprotocol. Other cases currently supported (e.g., a method declared in a subclass of
NSObject) would no longer infer
@objc, but one could continue to write it explicitly to produce Objective-C entry points.
As expected, there is a lot of debate in the review of SE-0159: Fix Private Access Levels on the lists. The community is somewhat mixed, but it seems there is mostly strong support for the proposal. As I’ve mentioned before, I strongly support this proposal as well. I think the introduction of
fileprivate (and later,
open) introduced unnecessary complexity in Swift’s access control story for very little tangible benefits. (I’d like to see
open removed as well, but I highly doubt that will happen. 😄)
In support of the proposal, Xiaodi Wu writes:
[…] the proposed solution itself is succinct, unambiguous, and easily understood. It does not argue that the new access level in Swift 3 has no merit, but rather that it has defects sufficient to merit a reversal to what we had before. The migration path is clear and unlikely to cause major problems. Therefore, as I agree with the arguments, I support the proposal.
However, real-world experience now demonstrates that
fileprivateis not rarely seen. In fact, as the data above bear out, it is very hard not to use
fileprivatewhen writing code in at least one very common Swift style (i.e. using same-file extensions). The point is well taken–but in the end it isn’t germane to the argument–that some styles of Swift code do not have to use
fileprivate. The point is that the core team’s acceptance of the design was based on a prediction that did not turn out to be true: namely, that idiomatic Swift would rarely need
fileprivate. As a consequence, more users now have to contend with more access modifiers than anticipated.
I disagree that there needs to be much more said about “complexity”–it is self-evident that four access modifiers are more complex than three. (And yes, I agree with previous arguments on this list that only two access modifiers are really necessary at all: internal and public.)
In opposition to the proposal, Matthew Johnson writes:
I am also -1. I think there are two issues to be considered. One is scoped access itself and the other is the names of the access levels.
I think a reasonable case can be made that changing the meaning of private and introducing fileprivate was a mistake. We probably should have left private alone and chosen a new name for scoped access. There was abundant bikeshedding over this at the time, but now we have the benefit of experience. I believe we should have simply called scoped access control
scoped. It’s clear that some people would still oppose scoped access but I also don’t think we’d be revisiting this topic if we hadn’t changed the meaning of
private. The passionate dislike of the feature seems to me mostly related to stealing the
I support correcting the naming mistake eventually. I’m neutral as to whether Swift 4 is the right time to do that. We just introduced a lot of churn in Swift 3. There is still inconsistency in Swift’s access control system as well as unmet needs (especially around submodules). It may be better to leave things alone for a release and make the change as part of a larger set of changes when access control and submodules are part of a release “theme”.
I am extremely unconvinced that having a scoped access level is actively harmful. It introduces another choice in the language but no individual programmers or teams are forced to use the additional flexibility if they don’t want to. It would be very easy for linters to prohibit scoped access if there are teams that don’t want to use it. It is one extra degree of control for new programmers to learn but properly taught it helps programmers learn to think about encapsulation. This is a good thing.
And finally — move fast and break things. 😏