WWDC22 brought so many new APIs that despite me watching and summarizing over 20 sessions in just the first week, I still haven’t watched all sessions I marked as favorite yet and am still watching 5–10 sessions a week. But I’m almost done now and my overall impression is that this year we got a lot of developer ergonomics improvements both in SwiftUI & Xcode and even the biggest star of the conference — the new Charts framework — adds to that.
Apple engineers also did a great job of introducing some of the new Swift features that are shipping with Swift 5.7, some of which we have covered in past issues of this newsletter. Here are some you might be interested in:
- Plugins: Meet Swift Package plugins & Create Swift Package plugins
- Generics: Embrace Swift generics & Design protocol interfaces in Swift
- Concurrency: Eliminate data races using / Visualize and optimize Swift
- Actors: Meet distributed actors in Swift (+ last year’s talk on Swift actors)
- Regex: Meet Swift Regex & Swift Regex: Beyond the basics
But let’s get back to what’s new in Swift Evolution to learn about some proposals that are also all going to improve developer ergonomics!
The following proposals already presented in the past have been accepted:
- SE-0352: Implicitly Opened Existentials (Rationale ✅)
- SE-0353: Constrained Existential Types (Rationale ✅)
- SE-0356: Swift Snippets (Rationale + Modifications ✅)
Proposals In Review/Revision/Awaiting Decision
For the following proposals, you can still provide feedback. The current rejection rate is less than 10%, so it’s likely they get accepted. Revisions are more common.
The following proposals already presented were returned for revision:
- SE-0354: Regex Literals (Rationale 🔄 | Review 🧵)
- SE-0357: Regex String Processing Algorithms (Rationale 🔄 | Review 🧵)
On to new proposals currently in review (or still awaiting a decision)!
SE-0359: Build-Time Constant Values
Have you ever found it inconvenient that initializing a
URL with a clearly valid String literal like
https://apple.com returned an
Optional? I did. I actually always force-unwrap them using by appending
!. But no more!
This proposal adds a new
@const attribute to type properties, function parameters, and even protocols. This will allow restricting APIs to only accept values that are known at compile-time — so basically, we will only be able to pass literal values to them. Future proposals will then be able to add functionality into the toolchain that will allow us to add validity checks at build-time for APIs that are marked with
@const, preventing us from shipping incorrect code. It also helps the Swift compiler further improve build time.
But that’s not all: This will allow for entirely new ways of using Swift, where merely building the code (but never executing it!) provides enough value, such as for the Swift package manifest file, which already has a pre-pitch to get the same treatment as Regexes have just gotten: A DSL-style syntax!
Does that mean we will be able to write a DSL language that can be easily used as a replacement for config file formats like YAML? Probably. The example mentioned in the proposal is a “build-time extractable database schema”. This is how a new Swift persistence framework could work. 😍
SE-0360: Opaque result types with limited availability
This basically widens the applicability of SE-0244: Opaque Result Types to very simple
if #available checks which is useful for framework authors. For example, the following example currently doesn’t compile because the
some Shape opaque result type requires that the body returns exactly one specific type, but we have two different return types (Rectangle and Square):
With this proposal, the above code would compile. But don’t get too hyped, the following already doesn’t compile due to the dynamic if condition:
So in most cases, you will still need to resort back to existential
any (SE-0335) or other means of type erasure if you have multiple return types. By the way, I strongly recommend watching the WWDC22 session Embrace Swift generics if you struggle with the new
any keywords and when to use which. It starts with a quick introduction to protocol-oriented programming, goes into how you can replace
where T: Animal with
some Animal, and then explains the differences between
any pretty well.
SE-0361: Extensions on bound generic types
This is another proposal for making generics more ergonomic by allowing a more natural and expected syntax when using them. In this proposal, extensions are tackled. In short, all of the 3 following extensions statements on a generic type would in the future compile and have the same meaning:
Note that this will only work if all generic type arguments are provided, so if you have a type with multiple generic types and you just want to specify one in your extension, you’d have to resort back to the
As you can see in the above examples, even syntactical sugar variants will be supported, including optionals. So you’ll be able to write
extension String?instead of
extension Optional where Wrapped == String.
SE-0362: Piecemeal adoption of future language improvements
Source-breaking changes in Swift are handled with great caution. So much so, that some new language features are already implemented and shipped with versions of Swift 4/5, but are disabled because they are marked as “only available in Swift 6 language mode”. Some of them shipped with a custom feature flag to turn them on today but even they are hard to explore.
This proposal streamlines that by adding the feature flag specifier
--enable-future-feature and requiring all future & even past proposals to adopt this by specifying their own feature identifier for it. This way developers have a unified way to enable and adopt select new features at their own pace.
This not only gives you the benefit of a Swift 6 improvement today but also allows you to easily prepare for Swift 6 on a step-by-step basis. I encourage you to turn on each feature one by one to see its impact to your code base as soon as the unified flags are available. This way you can discuss each feature with your team and create a roadmap for when to enable them to smoothen your transition to Swift 6 proactively.
Thanks to a new
#if hasFeature() check, it will even be possible to keep two versions of the same code to not have to change your code when enabling/disabling a feature or simply to support the integration of your framework into tools where the feature is not available. For example:
The adoption of specific features will also be possible by specifying an array of feature identifiers to a
target in SwiftPM manifest files like so:
Here’s a list of all initial feature identifiers that are planned to be supported:
ImplicitOpenExistentials(covered in April Issue)
BareSlashRegexLiterals(covered in May Issue)
Recently Active Pitches/Discussions
Some threads inside the “Evolution” category with activity within the last month I didn’t link yet. I’ll cover them in detail once they become proposals:
- `is case`: pattern-match boolean expressions: Discussion 🧵
- In-Line Tests: Discussion 🧵
- Introduce type-private access level: Discussion 🧵
- Eliding `some` in Swift 6: Discussion 🧵
- Move Function + “Use After Move” Diagnostic: Draft 📝 | Discussion 🧵
- SPM: Allow targets to depend on products in package: Discuss 🧵
- Conditional compilation for attributes and modifiers: Discuss 🧵
- Expose property name to property wrapper: Discuss 🧵
- Use `some` as “some specialization of generic type”: Discuss 🧵
- `#if hasSymbol` compile time check for availability: Discuss 🧵
- Isolated synchronous deinit: Discussion 🧵