Hello, it’s Paul Hudson here from Hacking with Swift. I’m not going to use this spot to sell you stuff, I just wanted to help support this awesome newsletter. Thanks for all your hard work, Jesse and co!
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.
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.
The @swift-ci bot got a cute new avatar!
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:
@NSCopyingwould 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
@NSCopyingneeds 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
didSetare 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.
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).
The proposal is accepted with the following revisions:
- The root
Numberprotocol should be renamed
- Instead of using single-case enums as mock trailing argument labels, the
ReportingOverflowvariants should include that information in their basename:
popcountshould use the unabbreviated name
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
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:
We propose to provide similar expressive power to Swift, which will also improve the bridging of those types from Objective-C.
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).
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.
Nevin’s final recommendations are to keep Swift 2’s original
private (to file),
public modifiers (removing
fileprivate). Then, remove
open and parameterize
final to accommodate the semantics of
open, for example
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(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 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 (
public) to worry about for the majority of developers. This kind of progressive disclosure (one of Swift’s strengths) is particularly important for beginners.
And finally — there’s always a party in San Jose.