Design Priorities for the Swift 6 Language Mode

As Swift evolves, it gains new features and enhancements as govered by the Swift Evolution process. Once implemented, new features become available in new versions of the tools, e.g., async/await was first available in the Swift 5.5 tools, and one will need to upgrade to newer tools to make use of those features. New features and enhancements must maintain source compatibility, meaning that the new Swift tools must still accept Swift code that was accepted by older Swift tools, so that Swift code written using the Swift 5.1 tools will still compile with Swift 5.5 tools and beyond. Source compatibility can have a significant effect on the overal design of features, and is explicitly part of the proposal process, but it still allows for major improvements to the language. For example, the entire Swift Concurrency effort, including async/await, structured concurrency, and actors, was introduced while maintaining source compatibility.

It is sometimes the case that a change that is desirable for the language will necessitate breaking source compatibility. Again, Swift Concurrency provides an example: the Sendable checking described in SE-0302 will cause a significant number of Swift programs to be rejected due to missing Sendable annotations. To address this issue, the Swift tools support multiple language versions. For example, the Swift 5.5 tools, support language versions 4, 4.2, and 5, whereas future Swift 6.0 tools would likely support language versions 4, 4.2, 5, and 6. The Sendable checking will be downgraded to warnings or suppressed in existing language versions (4, 4.2 and 5), which covers all supported Swift code, then enabled as errors for future language versions (6 and later). Developers explicitly adopt newer language versions, at which point they will adjust their code for the changes in that new language version, but doing so does not affect Swift code outside of the module that they are working on, because the language version is set on a per-module basis.

Swift language version 6, which we'll refer to herein as Swift 6, offers an opportunity to introduce a targeted set of source-incompatible changes to the language. Swift 6 must not change the fundamental shape of the language, nor make sweeping changes without purpose. Rather, it should only introduce changes that serve a specific goal that benefits the entire Swift ecosystem and is not achievable while maintaining source compatibility. Most features do not fall in this category, so major efforts that are underway in parallel with Swift 6---such as the ownership model or constant evaluation---will continue to be developed independently of Swift 6 unless some specific aspect of them requires source-incompatible changes, akin to the Sendable part of the Swift Concurrency effort.

Swift 6 focus areas

The Swift Language Workgroup has identified three focus areas where systemic improvements for Swift will depend on source-incompatible changes. Proposals that involve source-incompatible changes for Swift 6 should address one of more of these areas:

  • Data-race safety by default: Data-race safety by default is a significant shift to the model that can only be staged in with a new language version, but it has a large payoff because it makes concurrent programs far easier to write correctly. Swift 6 will need to tighten the semantics around Sendable and actor-isolation checking, but may also need additional changes or features to make working in that safety model easier.
  • Performance predictability: Swift presents an expressive and fairly high-level programming model that abstracts away unnecessary details. However, Swift development can encounter performance "cliffs" where a small change can cause unexpected degradation in the run-time performance of a program (e.g., due to excessive copying of copy-on-write data types) or the performance of Swift tools (e.g., "expression too complex" errors). Swift 6 could consider changes to the default language semantics that improve performance predictability, for example by tuning the rules concerning variable lifetimes, making some features that carry a runtime cost opt-in rather than opt-out, or tuning the type inference rules to enable a better-performing implementation of the type checker.
  • Package ecosystem scalability: The long-term health of the Swift language and community depends on having a robust ecosystem of packages. The Swift language and package manager might require adjustments to make it easier to grow the package ecosystem. For example, Swift's module system might be improved to limit the effect of a module's implementation dependencies on its client modules, making modules and packages more resilient to change.

The Language Workgroup will evaluate on a case-by-case basis any additional changes that provide sufficiently high value to the language relative to the cost of source incompatibilities they introduce. For example, Swift 6 may include proposals with source-incompatible changes where they are needed to finish a feature that cannot be completed otherwise, such as the regex literal parsing changes in SE-0354 or the requirement for 'any' on existential types introduced in SE-0335.

Swift 6 will also include bug fixes, where the Swift compiler previously accepted code that it shouldn't have, but the need for source compatibility requires it to continue to accept the incorrect code. For example, implicit references to weak self being non-optional in some cases is a compiler bug that needs to be addressed, but can only be done so when we are willing to introduce a source incompatibility in Swift 6.

Staging changes for Swift 6

Swift 6 will include a number of changes developed over the course of several years, parts of which will have already been implemented but are not available to developers. Swift 5.8 tools will introduce support for "upcoming" features, which allow source-incompatible Swift 6 changes to be explicitly enabled in a module that is built with Swift language version 4 or 5, on a feature-by-feature basis. This kind of piecemeal adoption of Swift 6 changes is important for several reasons:

  • Developers will reap the benefits from these improvements sooner, rather than wait until the Swift 6 language version is available and complete.
  • Making these changes available to developers prior to Swift 6 provides more experience, allowing us to tune them further for Swift 6 if necessary.
  • Incremental adoption of source-incompatible changes reduces source code churn, making each subsequent change easier and less risky.

It is important to note that upcoming features are not forks of the language. Rather, they are incremental steps along the path to Swift 6 that don't individually affect the overall character or feel of the language.

68 Likes

These benefits will not materialize unless we can ship packages that enable these flags, or packages that depend on other packages that do. As far as I can tell this still isn't the case due to SPM's rules around "unsafe flags". Will these restrictions be lifted or otherwise reconsidered, at least for the feature flags?

7 Likes

You're likely purposefully not stating this, but I'll ask anyway since it's been a couple years since the On the road to Swift 6 post was made.

Swift 6 probably still operates under the "it'll be done when it's ready" timeline, so I don't expect any sort of commitment. Is there a vague idea of when Swift 6 might be released? I mean the actual source compatibility break, features will still come in minor releases along the way.

Within a year? Years out still?

5 Likes

Upcoming features are enabled in Swift package manager manifests in a manner distinct from unsafe flags, and the proposal specifically discusses that they can be used in dependencies.

3 Likes

The proposal really doesn't say much, but I guess it means what you say:

SwiftPM would then pass each of the upcoming features listed there to the compiler via the -enable-upcoming-feature flag when building a module using this setting. Other targets that depend on this one do not need to pass the features when they build, because the effect of upcoming features does not cross module boundaries.

However, it also says:

Experimental features are still to be considered unstable, and should not be available in released compilers. However, by unifying the manner in which experimental and upcoming features are introduced, we can rely on the same staging mechanisms: a way to enable the feature and to check for its presence in source code, making it easier to experiment with these features. If a feature then "graduates" to a complete, supported language feature, hasFeature can return true for it and, if part of it was delayed until the next major language version, -enable-upcoming-feature will work with it, too.

So how are we to gradually adopt new features if none of the release compilers enable those features? The vast, vast majority of the Swift ecosystem never uses the prerelease toolchains, and small minority will try beta Xcode versions. So how can we "reap the benefits of these improvements sooner" if the improvements aren't available in releases? Or is there some nuance here that the proposal is missing?

These are good improvements, but are there no plans to take advantage of registry support with a properly secured, centralized registry? Until that's in place, Swift's ecosystem will be strictly inferior to most other languages, no matter how resilient our modules are in practice.

A centralized package repository seems out of scope for the language team.

Given they're the only ones who can possibly address it by integrating it into Swift itself, I don't know who else you think could do it.

2 Likes

You’re asking a technical team to commit to getting into the business of running and maintaining a centralized package repository. That’s not a problem within the scope of SwiftPM tool improvements.

Furthermore, your assertion that the lack of an ordained centralized repository makes Swift “inferior” is highly dubious.

2 Likes

Not especially, but this isn't really the place. I'm just pointing out that when the community thinks of ecosystem improvements, module resilience isn't what most people envision.

Doug's post is about the upcoming Swift 6 language mode. Adding a centralized package registry doesn't require a language mode, so you shouldn't expect any discussion of that here, no matter how interesting or important it might be.

You might have missed it, but we did make a blog post about a month ago talking about more general project priorities and upcoming work, and it does include information about SwiftPM and its work towards a package registry. If you'd like to talk about that, you might participate in the forums thread about that post, or you could find / start a thread in Development > Package Manager.

10 Likes

I mean, there could certainly be impacts to SPM's Swift 6 mode, but fair enough. Feel free to delete the digression.

Yes, that's the intent here. There's currently an open issue to make sure that these aren't treated as unsafe flags.

Are you conflating "upcoming" and "experimental"? "Experimental" are not fully implemented and not reviewed, so one shouldn't depend on them at all and they don't belong in release compilers.

"Upcoming" features are ones that have been reviewed and implemented and can be used with any compiler that supports them. We'll promote a feature from "experimental" to "upcoming" once it's been reviewed, accepted, and implemented.

Doug

14 Likes

Thanks for the clarity.

1 Like

Definitely not within the year.

Doug

27 Likes

Is this in reference to this issue? If so, I'm certainly excited for it.

1 Like

there is a big difference between maintaining a centralized package repository and a centralized package registry.

the latter seems like a very reasonable request, and something that i feel has been sorely missing for quite some time.

1 Like

As @John_McCall said, it’s not a reasonable request in the context of this discussion, which is about language modes.

1 Like

To be clear, I'm not weighing in about the idea itself, I'm just saying it's off-topic in this thread because it doesn't rely on a language mode.

I've been hoping that people would just let it lie, but if it keeps kicking up, I'll move the discussion to a separate thread.

5 Likes

Hi.
Can Swift / ObjC interop improvements be the priority for Swift 6 too? There are couple of missing capabilities (1, 2, 3) which can unlock other important developments like deterministic builds with llbuild, and proper ObjectiveC support by SPM.

2 Likes