Progress toward the Swift 6 language mode

Since the last update laying out the design priorities for the Swift 6 language mode, the project has been making steady advances towards this next milestone. However, some of the previously stated goals include open-ended research questions that are still in the early stages of development. Instead of holding up Swift 6 as this work progresses, the Language Steering Group is narrowing the focus of remaining changes for Swift 6 to data-race safety by default.

Readiness of data-race safety by default

There are still a number of bugs and holes in the Sendable checking model that admit data races under strict concurrency checking. Equally important, strict concurrency checking currently issues a significant number of false positive reports of data races, making the complete checking difficult to program against.

The Swift 6 language mode will only be declared ready once the Language Steering Group determines that the programming model is effective and usable. The remaining language work to complete data-race safety for the Swift 6 language mode will fall into two categories:

  1. Fill all holes in the strict concurrency model so that data races are diagnosed statically, or dynamically where static safety cannot be proven.
  2. Mitigate false reports of data races on patterns that are proven to be safe.

Swift 5.10 contains a number of significant bug fixes in the actor isolation and Sendable checking. In addition, the following language changes are currently being designed and implemented to undergo the Swift evolution review process:

Together, these changes fill the remaining major holes in strict concurrency checking and improve the usability of strict concurrency checking by introducing more Sendable inference and enabling safe ways to transfer non-Sendable values across isolation boundaries. The Language Steering Group acknowledges that other language changes in the area of concurrency are important, but the changes above are necessary for defining the Swift 6 language mode. Other concurrency features are additive and can be explored independently.

The Swift 6 migration

Upcoming features are critical for migrating to the Swift 6 language mode: one can enable individual upcoming features one at a time to incrementally move a code base toward Swift 6, before adopting the full language mode. There are a number of previously-accepted upcoming features that will be enabled by default in Swift 6:

The Language Steering Group has decided that one previously-accepted upcoming feature, ExistentialAny, will not be enabled by default in Swift 6. SE-0335: Introduce existential any introduces the any keyword to identify existential types. The proposal also specifies that "bare" protocol names will no longer be permitted as types---they must either use any or some, as appropriate---under the upcoming feature flag ExistentialAny. Given the concerns about migration to consistent use of existential any in the language, and the expectation that additional language improvements will be coming that might affect the end result of that migration, the Language Steering Group is deferring the source-incompatible changes in SE-0335 to a future language revision.

Additional evolution proposals may include source-incompatible changes for Swift 6, and the Language Steering Group will evaluate such proposals on a case-by-case basis for high value to the language relative to the cost of source incompatibilities. For example, sufficiently high value changes might include minor type inference changes that are necessary for completing a major feature, such as typed throws, or semantic changes in pursuit of data race safety.

Once all of the upcoming features for Swift 6 are in place, the Language Steering Group will provide a migration guide that suggests an optimal path for incrementally enabling strict concurrency checking in a project, along with practical guidance on how to address certain kinds of strict concurrency violations in common code patterns. Community feedback on these guides will be critical to evaluating the approachability of the Swift 6 migration.

66 Likes

Great to see all of the work on fixing Sendable holes and making it easier to use. We have seen a lot of new warnings in our Swift on Server repositories and those have uncovered real data races! Can't wait to see how region based isolation is going to make even more safe patterns compile-time safe.

One thing that came up again in our recent Swift on Server workgroup meeting w.r.t. Swift 6 is the long standing issue of non-extensible enums for libraries in non-library-evolution mode. This has caused significant pain over the past years and continues to be a sharp edge for developers which often lead to accidental API breaks. Furthermore, with the introduction of swift-foundation this becomes more important since swift-foundation ships a number of non-frozen enums which behave differently in the two modes. I know this is an update post but I just wanted to voice our recent discussions in the SSWG here again.

14 Likes

I was actually working on that recently when I uncovered this hole, which I also hope can be patched in Swift 6.

That said, I think non-frozen enums are an additive change. I highly doubt we are going to change the default behaviour of enums, so you're going to have to opt-in to extensibility via some kind of @nonfrozen attribute (although now we have a notion of cross-module-but-same-package in the compiler, there would likely be less breakage than previously expected).

The language steering group discussed this issue also, and an announcement on it will follow shortly.

10 Likes

what about Noncopyable Generics ?

We don't expect generics for non-copyable types to change the rules for existing code, so it won't be limited to a specific language mode.

4 Likes

Great: Swift 6 looks doable and valuable!

(Edit: removed as presumably off-topic)

2 Likes

It's been several years talking about Swift 6 and breaking changes. Is there a plan to release a language breaking version every few years?

Any plans to have an ABI-breaking version one day to be able to address some of the language warts and design choices that would be nice to rethink?

6 Likes

Swift is ABI-stable only on Darwin platforms. An ABI break there would break system libraries that are written in Swift, and apps that use them as a consequence.

1 Like

There is no specific plan to have a regular cadence of new language modes. As time goes on, the burden for major breaks increases, and we’ll need strong justifications for them. Most of the breaks in Swift 6 are very minor; the exceptions are all in service of concurrency safety, which is a major goal for the language.

The Language Steering Group is already looking at what might justify major breaks for a hypothetical Swift 7, if anything. Right now, the main thing that would qualify to me would be changes that would rein in the exponential expectations on the type-checker. Getting that right without being too disruptive could be quite a long project, though.

18 Likes

To put this more strongly: on platforms which promise ABI stability, no ABI breakage is considered acceptable due to risk to end users of those platforms.

Source breakages can be considered with language modes because they require recompilation in order take effect, and affect only developers; ABI breakages lead to existing binaries no longer behaving as expected (usually by crashing, but sometimes by silently corrupting data).

4 Likes

Is that inevitable, though? I don't know the details of how Swift implements its ABI and library versioning, but in other languages & packaging systems (e.g. Objective-C frameworks) there are specific mechanisms for supporting multiple ABIs (e.g. look in any framework and see that it contains a Versions folder, usually with just an A subfolder, but you can in fact have B, C, etc and link against specific versions).

The "we can never change the ABI" doesn't really seem viable, any more than it would be to say "we can never remove any API or framework". Imagine if every framework and API therein, that Apple has ever shipped since MacOS X Developer Preview 1, had to still be in macOS Sonoma (and still fully functional, lest that lead to applications crashing or corrupting data).

1 Like

Except in extenuating circumstances, this is actually how system frameworks on Darwin platforms typically work: code is overwhelmingly only deprecated, not removed. Certain frameworks have been phased out over time (e.g., Carbon), but over the span of decades and not years, after the vast majority of clients have already migrated off. APIs are basically only removed either by accident, or when the entire framework goes away after an extremely long deprecation period (if ever). Foundation, for example, does contain code that spans all the way back to its introduction (... and earlier), even though you'd never use those APIs today (and new usage is highly discouraged) — see, e.g., NSConnection and the Distributed Object APIs.

Support for multiple ABIs would be excellent, though it's not an ABI breakage. If we did want to make ABI changes, this would necessarily be the path forward; it's just not something that, to my knowledge, Swift supports today.

(Some languages [cough C++ cough], by the way, have in the past decided to simply break ABI and say "tough luck" to all existing clients and binaries... But that's just not an acceptable position for frameworks that ship with the system.)

11 Likes

I’ll note the B, C, etc subsystem is basically considered dead because it forks the entire downstream module graph. It’s like introducing a new platform architecture, but without actually having a new architecture: everything downstream needs to be recompiled to work together, and you have to maintain two variations and have twice the code on disk until the old architecture goes away.

(Which, by the way, is the most likely opportunity for ABI improvements on Apple platforms, if they ever switch to aarch128 or riscX or whatever. But that’s probably a long way off, and not under the Swift community’s control, and still doesn’t remove the old architecture for many years after that.)

4 Likes

Carbon was removed during the transition from 32-bit to 64-bit. OpenTransport was removed some time before that. Also: QuickDraw GX in pre-OSX days.

If frameworks are being removed less frequently, that's a good thing for application developers. Some of these changes were very disruptive.

Yep, it has a cost. It's not something that Apple has ever done for public frameworks, that I'm aware of. But I believe it was done for private frameworks (I specifically recall dealing with this for a private framework when I was at Apple, eons ago).

There's also clearly technical avenues for ameliorating that, such as only installing the "old" versions of frameworks on-demand.

Exactly. There's nothing in the foreseeable future that's going to be a convenient excuse to clean house. That's why I think it's worth looking at other options.

Also, keep in mind that Apple does quite often break applications, sometimes in pretty serious ways, between OS releases. Not through relatively clean methods like removing frameworks or breaking ABIs, but by silently changing the runtime behaviour of frameworks. Sometimes they even do that knowingly and deliberately, in apparent ignorance or disregard of its impact on developers and end-users. So I think the "Apple can't break ABI because it would be unprecedented" [aspect of the] excuse is functionally false.

3 Likes

As others have noted, the Versions folder approach is a dead-end. Note that it only exists in the macOS SDK (where there is only ever a single version, usually A) and none of the Apple SDKs for newer platforms (iOS, watchOS, etc.) have it.

As for how Swift approaches ABI stability, I gave a talk on the subject last year that goes into the goals and technical details.

We're really far afield now from the original topic of this point. The answer to the original question is: it is unlikely that there will ever be ABI-breaking changes to Swift, at least not in the foreseeable future, but with enough effort we can stage in most anything we need in ABI-compatible ways.

Doug

16 Likes
Aside

For the curious, Carbon deprecation effectively began in 2007 with the Intel transition (Carbon was intentionally never ported to 64-bit), and over time, various APIs were more explicitly deprecated. IIRC, updates to Carbon APIs stopped coming around the Mountain Lion timeframe, the final removal only came when 32-bit support was dropped altogether — I believe announced in with High Sierra, but only happened with Catalina? So, quite a lifecycle...

3 Likes

what would it take to solve CommandLine.arguments and CommandLine.argc should be deprecated and replaced with immutable equivalents. · Issue #66213 · apple/swift · GitHub ?

2 Likes

I seem to remember that Carbon was ported to 64-bit PowerPC, and that an x86-64 port of Carbon was announced (and might have even been available in a beta release of OS X) then canceled shortly after. But that was just the UI layer of Carbon, I believe a few bits of the non-UI parts of Carbon might still exist on MacOS even today.

2 Likes