What happened since last week other than the Internet bursting into flames? Let’s find out! 😄

News and community

The Mozilla mobile team wrote about their migration to Swift 3.0 for Firefox for iOS. It’s another in-depth look from the community at the pain, sweat, and tears involved in migrating. If we’re lucky, this will be one of the last posts we see like this. The unique thing about Firefox is that the entire app is open source, so you see the details up close. The good news, however, is that future versions of the Swift compiler (beginning with 3.1) will feature a “compatibility mode” which should help ease these kinds of transitions — not to mention, source-breaking changes now undergo much more scrutiny.

Craig Hockenberry wrote an article, Swift Changes Considered Harmful. He notes a very practical negative impact of Swift’s rapid evolution, that WWDC sample code from 2016 no longer compiles and StackOverflow answers are often outdated — resulting in a detrimental experience for beginners. There’s at least one solution here: Apple should update all Swift code samples for Swift 3.0 or provide sample code in Objective-C.

Keith Smiley had one of those “this StackOverflow answer should be a blog post” moments, answering a question about dumping the Swift AST of an app. And then he wrote some scripts to help! 👏 🙌

Thanks to Peter Steinberger, I discovered Sandy Martel’s swiftpp project. “swiftpp is a clang tool that automatically generates the glue code to let a swift class inherit from a C++ class. You can override C++ virtual methods from the swift derivative as well.”

Another project of note is Tulsi — an Xcode Project Generator for bazel, Google’s build tool. (Similar to Facebook’s buck.) If everyone keeps building their own build tools, I’m sure one of them will eventually mostly work most of the time. 😄 Maybe Xcode should be open source?

Commits and pull requests

Last week I lamented Graydon Hoare’s revert of the bridging PCH feature by default. This week Ted Kremenek reverted the revert to again make bridging PCH the default. I heard the Core Team likes reverts.

Roman Levenstein (@swiftix) merged improvements to the SIL optimizer, resulting in reducing the code size of the stdlib by about 9.4%.

Ben Cohen (@airspeedswift) got the 👩‍❤️‍👩 emoji working on the unicode-rethink branch.

Nate Cook (@natecook1000) added a benchmark for quadratic hash performance to help address SR-3268.

Nethra Ravindran (@nethraravindran) fixed a memory leak in NSURLComponents in corelibs-foundation.

The @swift-ci bot got a cute new avatar!

Accepted proposals

SE-0153: Compensate for the inconsistency of @NSCopying’s behaviour was accepted for Swift 4.

The proposal is accepted using the “compiler magic” approach, where the compiler will introduce the copy within the initialization to maintain the invariant that the stored property is always initialized with or set to a copy of the provided value.

Feedback from the review was mixed. There was general agreement that this was a real problem that does require a solution, but the discussion during the review slightly favored the more conservative approach of adding a warning in the compiler. This was based on two main concerns about introducing the copy within the initializer:

1) @NSCopying would act differently from didSet, the latter of which still would not be called within initializers, and 2) Concern that property behaviors would not be able to model the semantics described here.

The core team felt that @NSCopying needs to guarantee that the copy occurs under all circumstances, and that a change in language semantics here is warranted. Regarding concern (1), the core team felt that @NSCopying and didSet are different enough that different behavior is reasonable and expected. Regarding concern (2), the core team noted that property behaviors can model the new semantics by providing behaviors with an extra customization point that is invoked from within the initializer (and does not have access to “self”). Moreover, having this customization point in property behaviors will make concern (1) less acute, because property behaviors can and will differ in their initialization vs. setting behavior.

SE-0154: Provide Custom Collections for Dictionary Keys and Values was accepted for Swift 4.

Feedback was generally positive, and the core team felt that this proposal was a useful step forward for Dictionary, providing more flexibility for the standard library ABI and better performance. However, the core team noted that acceptance of this proposal should not preclude improvements to the ergonomics of Dictionary, even for the use cases described in the proposal itself (e.g., inserting an empty collection if it isn’t already there, and appending a value to the collection).

SE-0104: Protocol-oriented integers was accepted.

The proposal is accepted with the following revisions:

  • The root Number protocol should be renamed Numeric.
  • Instead of using single-case enums as mock trailing argument labels, the FullWidth and ReportingOverflow variants should include that information in their basename:

multipliedFullWidth(by:)
dividingFullWidth(_:)
addingReportingOverflow(_:)
subtractingReportingOverflow(_:)
multipliedReportingOverflow(by:)
dividedReportingOverflow(by:)

  • popcount should use the unabbreviated name populationCount.

The core team also observed that the proposed endianness-handling interfaces deserve further thought. In almost every known little-, big-, or mixed-endian format, converting to and from another endian are symmetric operations (going to and from big endian are the same operation, as are going to and from little endian), so there is no need for both sets of operations to be independent protocol requirements. The core team accepts the proposal as is for now, since it’s a small corner of the larger proposal, but asks the authors for a follow-up proposal in this space.

Proposals in review

SE-0156: Class and Subtype existentials by David Hart and Austin Zheng is under review.

This proposal brings more expressive power to the type system by allowing Swift to represent existentials of classes and subtypes which conform to protocols.

Currently, the only existentials which can be represented in Swift are conformances to a set of protocols, using the & protocol composition syntax: Protocol1 & Protocol2.

On the other hand, Objective-C is capable of expressing existentials of classes and subclasses conforming to protocols with the following syntax: id<Protocol1, Protocol2>, Base<Protocol>*.

We propose to provide similar expressive power to Swift, which will also improve the bridging of those types from Objective-C.

SE-0157: Support recursive constraints on associated types by Douglas Gregor, Erica Sadun, and Austin Zheng is under review.

This proposal lifts restrictions on associated types in protocols. Their constraints will be allowed to reference any protocol, including protocols that depend on the enclosing one (recursive constraints).

Mailing lists

There were a number of access control discussions this week, many rehashing ideas discussed during original review of SE-0025, the proposal that introduced fileprivate. Nevin Brackett-Rozinsky started a thread, A Comprehensive Rethink of Access Levels in Swift. It’s a thorough and thoughtful write up.

There has been a deluge of discussion about access levels lately, all attempting to simplify the situation. Shortly after Swift 3 was released, many people realized that the new access modifier story was far more complex than the old one, and expressed the belief that the changes may have been a mistake.

In the months that followed, more and more people came to share the same view, and stage 2 of Swift 4 has seen a profusion of proposals addressing the issue. These proposals are generally small and focus on changing just one aspect of access control. However, given the situation we are in now, it is important to look at the problem in its entirety and arrive at a cohesive solution.

[…]

That belief, as well as the numerous arguments which led to it, were well-informed and thoughtfully considered. However, due to the inevitable linear nature of time, they were not based on first-hand experience with the new changes. Upon the release of Swift 3, we all gained that first-hand experience, and it quickly became apparent to many people that the new access control system was needlessly complicated, and not at all the improvement it had been heralded as.

[…]

It is important that we as the Swift community are able to recognize our mistakes, and even more important that we fix them. We originally thought that the Swift 3 access control changes would be beneficial. However, experience with them in practice has shown that not to be the case. Instead, the language became more complex, and that has real costs. It is time for a simplification.

Continue reading…

Nevin’s final recommendations are to keep Swift 2’s original private (to file), internal, and public modifiers (removing fileprivate). Then, remove open and parameterize final to accommodate the semantics of open, for example final(public) or final(internal).

I definitely agree with the first part, but not the second — and it’s probably safe to say that this is not going to happen given Swift 4’s constraints and higher standards for source-breaking changes. This goes for other similar suggestions on the mailing list too, things like private(file), private(module), etc. I can tell you now, this is not going to happen! Such changes are too drastic and too disruptive, and were previously discussed and rejected.

I think the simplest, most reasonable, and less intrusive path forward is to simply revert SE-0025. That would leave us with private (to file), internal, public, and open. With internal being the default, it never has to be written. And only library authors (typically more advanced users) would need to know and understand open. That leaves only 2 access modifiers (private and public) to worry about for the majority of developers. This kind of progressive disclosure (one of Swift’s strengths) is particularly important for beginners.

Finally

And finally — there’s always a party in San Jose.