With Swift 4 development wrapping up, this week the goals for Swift 5 were announced! There are a lot of things to unpack in this announcement, but two main topics stand out — ABI stability and changes to the Swift Evolution process.

First, ABI stability is not merely a goal for Swift 5, but a requirement for the release. Notably, this is the first Swift release to have a hard requirement like this. As Ted discussed in the email, whatever ABI we have at the end of Swift 5, that’s what we’re stuck with! So there you have it, no more ABI stability delays! This likely means that iOS 12 could be the first release to ship with Swift, no longer requiring application developers to bundle the Swift runtime and standard library with their apps.

Secondly, the Swift Evolution process will see substantial changes. If you recall, the Swift 4 development cycle was split up into two “phases” in an attempt to address the somewhat chaotic churn of proposals that we saw during the development of Swift 3. The intent of Swift 4’s phases was to keep the release focused on meeting its goals, but this didn’t quite work out as expected. Thus, beginning with Swift 5 proposals are required to have an implementation before being officially reviewed by the Core Team.

There’s some concern in the community that this raises the bar too high for proposals and participation will decrease dramatically as a result. However, this new rule does not mean that the proposal author is required to implement the changes. It only specifies that an implementation must be available in order to be reviewed. Thus, multiple contributors can collaborate on writing and implementing. Despite the potential downsides, I’m in favor of this change. I expect it reduce much of the distraction and pure bikeshedding that happens sometimes on the mailing lists. And practically speaking, I honestly don’t see any other option given the importance of ABI stability — have you seen how much work is still left to do? 😅 Another benefit of this is that we could see the actual impact of the proposal on real-world code and include that as part of the review process. This will hopefully avoid another debacle like the access control controversy of Swift 3.

Start your engines! 🏎

Starter tasks

  • SR-5615: Improve diagnostic “public modifier cannot be used in protocols”
  • SR-5614: NS_EXTENSIBLE_STRING_ENUM on a typedef NSString crashes the compiler / source editor
  • SR-5605: Parser fails on optional #keyPath in enum case

Submit a task by sending a pull request or opening an issue.

Swift Unwrapped

Episode 23: ABI Stability – Data Layout and Metadata. Following last week’s episode on the big picture of ABI Stability, we focus on two categories of decisions that need to happen to get there: data layout and metadata.

News and community

Xcode 9 beta 5 was released, along with other betas. (Release notes).

You can find the list of Swift 5 goals here.

From Slava Pestov on Twitter:

If you have an idea for a contribution to the Swift compiler but aren’t sure where to start, please don’t hesitate to reach out

Commits and pull requests

Roman Levenstein merged changes to reduce the stdlib size by 200KB.

Back in Issue #71, we covered George Karpenkov’s pull request to add support for the -sanitize=fuzzer flag. This was finally merged this week.

Michael Ilseman opened a pull request to change String.CharacterView from being its own slice type to use Substring.CharacterView instead, as well as making it RangeReplaceable. “This aligns with the goal of introducing Substring as a separate type to avoid accidental memory ‘leaks’.” The PR also removes some old Unicode 8 code.

As mentioned in detail below, Ted Kremenek officially announced the Swift 5 goals. Here’s the diff for the Swift Evolution README if you’re interested.

Per the new “rules” for Swift Evolution proposals (where proposals must be accompanied by an implementation prior to formal review), there is a new label on GitHub, core team: needs implementation to denote proposals that have a lot of traction in the community and/or that the Core Team is interested in pursing. Ted Kremenek commented on two such draft proposals (PR #707, PR #705). One aims to remove ownership keyword support in protocols, and the other aims to deprecate “tuple shuffle” expressions. Chris Lattner commented on a third (PR #609) which seeks to refine identifier and operator symbology.

Proposals in review

SE-0185: Synthesizing Equatable and Hashable conformance by Tony Allevato is under review. This is the first proposal up for review for Swift 5, and (as required) you can find an initial implementation at PR #9619.

Developers have to write large amounts of boilerplate code to support equatability and hashability of complex types. This proposal offers a way for the compiler to automatically synthesize conformance to Equatable and Hashable to reduce this boilerplate, in a subset of scenarios where generating the correct implementation is known to be possible.

[…]

In general, we propose that a type synthesize conformance to Equatable/Hashable if all of its members are Equatable/Hashable. We describe the specific conditions under which these conformances are synthesized below, followed by the details of how the conformance requirements are implemented.

[…]

The ideas here are very much the same as the Codable protocol introduced in Swift 4, where all you have to do is declare conformance and the compiler will synthesize the rest. If all of a type’s properties are Equatable and Hashable, then the type itself could be too. I expect this proposal to have overwhelming support from the community, especially given the precedent set by Codable and other synthesis that the compiler currently does.

Mailing lists

As mentioned, Ted Kremenek officially announced the goals for Swift 5 as the development cycle for Swift 4 is winding down and nearing final release. Consideration of proposals for Swift 5 begins now! 🎉

The proposal phase for Swift 4 is now officially over, and the release is now in endgame engineering convergence for an expected release later this year. Swift 4 has turned out to be one of the highest quality, well-rounded releases of Swift, and I am grateful to everyone in the community who made this release come together!

Now it is time to turn our attention to Swift 5. I have just posted updates to the README.md file […]

I am not going to repeat all of that information here, but I wanted to highlight a few important things.

ABI Stability

First, ABI stability is the center focus of Swift 5 — and we will pivot much of our prioritization of efforts for Swift 5 around it. With Swift 4, ABI stability was a strong goal. In Swift 5, it is a requirement of the release. Whatever ABI we have at the end of Swift 5 is the ABI that we will have. ABI stability is an important inflection point for the maturity of the language, and it cannot be delayed any longer. […]

Other focus areas (including laying the groundwork for concurrency)

There are several other areas mentioned for Swift 5 which I won’t repeat here, but there is a general theme of refining and broadening out the core ergonomics of the language and standard library.

One of those that I wanted to highlight is laying the groundwork for concurrency. It is a non-goal of Swift 5 to roll out a full new concurrency model. That is simply too large an effort to do alongside ABI stability. However, it is important that we start making progress on discussing the directions for concurrency and laying some of the groundwork. […]

Changes to the language evolution process

Last, I want to highlight important changes to the evolution process:

With Swift 4, the release period was divided up into “stage 1” and “stage 2” for setting guidelines for the kind of evolution proposals that were in scope for the release. This was needed to establish focus — especially after the churn we saw during Swift 3 — on some core themes that were aligned with converging the language towards source & ABI stability. One downside is that “stage 2” opened up discussion for potentially disruptive changes fairly late in the release. Further, some proposals — such as SE-0155 — came in so late that there was little runway to actually implement them for Swift 4, let alone evaluate their impact in practice on real projects. Related, there has been some desire for a while to be able to better evaluate the impact of proposals on real code before they are locked into the release, and the best way to do that is to actually have an implementation that vets out the design in a proposal.

With Swift 5, the focus on ABI stability will predominate priorities for both design and implementation work, but the Core Team did not want that focus to stifle all discussion on potential enhancements to the language that were not fundamentally tied to that primary goal. After reflecting on the evolution process during both the Swift 3 and Swift 4 releases, the Core Team felt that we could strike a balance with not diluting attention from ABI stability while still enabling a broader range of proposals compared to Swift 4 by requiring that all proposals have an implementation before they are officially reviewed by the Core Team. An implementation can come long after an idea has been pitched and after a proposal has been written. However, before a pull request for an evolution proposal will be accepted — and thus an official review scheduled — an implementation must be in hand for a proposal as part of the review. The existence of an implementation does not guarantee that the proposal will be accepted, but it is instrumental in evaluating the quality and impact of the proposal.

There are two key benefits of requiring an implementation:

  1. It encourages a design in a proposal to be more thoroughly fleshed out before the proposal is formally reviewed. The hope is that this will make the review process both more efficient as well as more effective.
  2. An implementation allows the proposal to be evaluated on real world code and not just the examples that are in the proposal.

[…]

Requiring an implementation naturally raises the bar for proposals. While this is by design, it can possibly have the negative aspect of making some feel the bar is too high for them to participate in the Swift evolution process. As an open source project, both the design and implementation of the language is a highly social endeavor, and we encourage the community to collaborate on both the design and implementation of proposals. Specifically, it is not a requirement that the original author(s) of a proposal be the one who provides an implementation — all that matters is that there is an implementation when a proposal gets reviewed.

Continue reading…

Jordan Rose started a discussion on Enums and Source Compatibility, elaborating on how to allow (or not allow) extending enums (i.e. adding additional cases) while maintaining both source and binary compatibility. This is an important design decision for ABI stability.

Hi, everyone. Now that Swift 5 is starting up, I’d like to circle back to an issue that’s been around for a while: the source compatibility of enums. Today, it’s an error to switch over an enum without handling all the cases, but this breaks down in a number of ways:

  • A C enum may have “private cases” that aren’t defined inside the original enum declaration, and there’s no way to detect these in a switch without dropping down to the rawValue.
  • For the same reason, the compiler-synthesized init(rawValue:) on an imported enum never produces nil, because who knows how anyone’s using C enums anyway?
  • Adding a new case to a Swift enum in a library breaks any client code that was trying to switch over it.

(This list might sound familiar, and that’s because it’s from a message of mine on a thread started by Matthew Johnson back in February called “[Pitch] consistent public access modifiers”. Most of the rest of this email is going to go the same way, because we still need to make progress here.)

At the same time, we really like our exhaustive switches, especially over enums we define ourselves. And there’s a performance side to this whole thing too; if all cases of an enum are known, it can be passed around much more efficiently than if it might suddenly grow a new case containing a struct with 5000 Strings in it.

[…]

Just to have something to work off of, I propose the following:

  1. All enums (NS_ENUMs) imported from Objective-C are “open” unless they are declared “non-open” in some way (likely using the enum_extensibility attribute mentioned above).
  2. All public Swift enums in modules compiled “with resilience” (still to be designed) have the option to be either “open” or “closed”. This only applies to libraries not distributed with an app, where binary compatibility is a concern.
  3. All public Swift enums in modules compiled from source have the option to be either “open” or “closed”.
  4. In Swift 5 mode, a public enum should be required to declare if it is “open” or “closed”, so that it’s a conscious decision on the part of the library author. (I’m assuming we’ll have a “Swift 4 compatibility mode” next year that would leave unannotated enums as “closed”.)
  5. None of this affects non-public enums.

(4) is the controversial one, I expect. “Open” enums are by far the common case in Apple’s frameworks, but that may be less true in Swift.

Why now?

Source compatibility was a big issue in Swift 4, and will continue to be an important requirement going into Swift 5. But this also has an impact on the ABI: if an enum is “closed”, it can be accessed more efficiently by a client. We don’t have to do this before ABI stability—we could access all enums the slow way if the library cares about binary compatibility, and add another attribute for this distinction later—but it would be nice™ (an easy model for developers to understand) if “open” vs. “closed” was also the primary distinction between “indirect access” vs. “direct access”.

Continue reading…

Finally

And finally — the new Swift Evolution, it’s a match!