This week 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!

Swift Unwrapped

Episode 3: Source Stability (What is a Source Breaking Change?)

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

LLVM 4.0.0 was released this week. Congrats to those involved!

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

In the last couple of issues, we discussed the removal and resurrection of swift-stdlib-tool. This week, Ted Kremenek made the tool open source!

Manav Gabhawala (@manavgabhawala) opened a pull request that implements a robin hood algorithm for hash collisions in Set and 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.

Ankit Aggarwal (@aciidb0mb3r) implemented SE-0158, redesigning the Swift Package Manager API. The API now adheres to the Swift 3 guidelines! 🎉

Accepted proposals

SE-0156: Class and Subtype existentials was accepted.

The proposal was very well-received and is accepted with one modification: the ordering rules for existential types that involve AnyObject or a class type will be removed.

The ordering rules were intended to improve code clarity by requiring that the class (or AnyObject) constraint come first - AnyObject & P would be well-formed but P & AnyObject would 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.

SE-0157: Support recursive constraints on associated types was accepted.

The feedback on the proposal was unfailingly positive. Accordingly, the proposal has been accepted without further modification.

SE-0158: Package Manager Manifest API Redesign was accepted for Swift 4.

The proposal is accepted with the following revisions:

  • The To in upToNextMajor and upToNextMinor will be capitalized.
  • upToNextMajor() and upToNextMinor() will name the first parameter from: for clarity.
  • .only will be removed, as it was duplicative versus .exact.
  • We will have cases for .branch and .revision version 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

SE-0159: Fix Private Access Levels by David Hart is under 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.

The private keyword 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 private such 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 fileprivate.

[…]

The private keyword should be reverted back to its Swift 2 file-based meaning and the fileprivate keyword should be deprecated.

SE-0160: Limiting @objc inference by Doug Gregor is under review. Notably, the review manager is Chris Lattner. 😄

One can explicitly write @objc on any Swift declaration that can be expressed in Objective-C. As a convenience, Swift also infers @objc in a number of places to improve interoperability with Objective-C and eliminate boilerplate. This proposal scales back the inference of @objc to only those cases where the declaration must be available to Objective-C to maintain semantic coherence of the model, e.g., when overriding an @objc method or implementing a requirement of an @objc protocol. 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.

Mailing lists

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 fileprivate is not rarely seen. In fact, as the data above bear out, it is very hard not to use fileprivate when 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.)

Continue reading…

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

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.

[…]

Continue reading…

Finally

And finally — move fast and break things. 😏