Is there a way to use Swift 6 without SWIFT_STRICT_CONCURRENCY=COMPLETE?

Swift 6 introduces a couple of cool features which I would like to use, but there is zero hope of compiling my 10000 lines of code project in Swift 6 mode - because of strict concurrency checking.

My code is perfectly safe and bug free, and it's guaranteed dynamically. I am not willing to use either the actor-based synchronization model, nor the Swift structured concurrency altogether.

And please to not suggest to eliminate the "strict concurrency checking"-produced errors - my goal is to move on to Swift 6 without "strict concurrency checking".

How can I use Swift 6, but still be allowed global mutable non-actor isolated variables?

(All of this is of course an imaginary situation)

1 Like

The Swift 6 compiler defaults to the Swift 5 language mode with no concurrency warnings. I believe all of the Swift 6 features are available when running in the Swift 5 mode, so you should just be able to do what you want.

The Swift 6 migration guide has three documents that might be helpful as well. It covers how to control these features in Swift 5 mode, how to move to the 6 mode, and how to selectively enable Swift 6 features that could affect source compatibilty.

https://www.swift.org/migration/documentation/migrationguide

1 Like

What will happen after Swift 6? If we still don't want to use strict concurrency checking.

The Swift 6 compiler still supports the Swift 4 language mode, which was released in 2017. And this was a far more significant change.

Are there features that you won't be able to use if you use Swift 4 language mode in the later compiler versions though? Though I just tried to use say regex literals in a project with Swift 4 language mode and it compiled so I'm a bit confused.

From what I understand, some new evolution features do require the Swift 6 language mode turned on, and not just the Swift 6 compiler.

1 Like

You can use most of the features of Swift 6 by enabling various upcoming features. These are visible in Xcode 16, or you can pass the values directly to the compiler. The migration guide contains the flags enabled in Swift 6 mode.

3 Likes

Swift 6 supports spelling this directly. For 'I promise I won't cause data races on this particular declaration' the spelling is nonisolated(unsafe) var x: T. For 'I promise that values of this type dynamically prevent any data races' the spelling is struct S: @unchecked Sendable { ... } (or class, etc.).

9 Likes

Just to be really clear, this is not the case. I don't think there is a single Swift 6 feature that requires the 6 mode.

3 Likes

I mean, you won't be able to fully migrate without eventually enabling them. You can do that gradually though, as @Jon_Shier pointed out to the migration guide.

This one is actually can be easily avoided (if we talk about temporary solution) using nonisolated(unsafe) on globals. This will work even with Swift 6 mode on.

If you are going to usr Swift Concurrency features, it makes a lot of sense to migrate to strict checks eventually (say in a year or two, I guess more or less realistic timelines for large projects that cannot be stopped and migrated), since otherwise you not only missing valuable checks from the compiler, you also might have a lot of concurrency issues you are not aware with the new concurrency.

Perhaps “strict concurrency checking” was a misnomer… “complete concurrency checking” might have been a more accurate description.

2 Likes

I wonder what the default values ​​are for -strict-concurrency=<value> and -swift-version <vers> command line parameters of the swiftc v6.0 compiler?

Possible values for them are minimal, targeted, complete; and 4, 4.2, 5, 6 respectively. But it is not clear what values ​​are used by default.

1 Like

Strict checks still need to be explicitly enabled with Swift 6 compiler.

Yeah, this deserves clarification. By default Swift 6 compiler won’t make any concurrency checks, as it has Swift 5 mode. Strict concurrency checks require separate enabling, and will provide the same experience as with Swift 5.x compiler (some will be errors, lots will be warnings). With Swift 6 mode enabling then turn on complete checks making everything to be error.

In long term, if someone uses new concurrency, it is beneficial to migrate to from no checks, through strict checks and partial enabling of features, to the complete checks.

I also find meaningful to start with strict concurrency checks + région-based isolation + inference of Sendable features turned on as they help a lot to address warnings (partially by simply removing part of them by just turning on).

The defaults for the Swift 6 compiler are the 5 mode with minimal checking. Same for a new project with Xcode 16.

2 Likes

Xcode project settings show a "Strict Concurrency Checking" drop-down even when Swift 6 is enabled. The Apple Swift 6 migration guide also shows an upcoming feature flag StrictConcurrency, which controls other Swift 6 upcoming feature flags like RegionBasedIsolation too. This seems to imply that Swift 6 can selectively control the level of concurrency checking.

I don't think this is a great solution. If you add this everywhere, you'll forever suppress these warnings even if you want to try for strict concurrency again sometime in the future. Sure you can grep for them but having one single flag is much easier.

I agree that these should not be used generally as a mechanism for suppressing warnings—but the original question was with respect to a hypothetical codebase which manually guarantees its data-race safety via other mechanisms and so wishes to opt out of the static checks enabled by the Swift 6 language mode. nonisolated(unsafe) and @unchecked Sendable are the language tools to do that!

4 Likes

nono, the docs of Xcode build settings explicitly say, that SWIFT_STRICT_CONCURRENCY is treated as "complete" if the lang version is Swift 6, and the custom value is ignored.

2 Likes

What about turning off upcoming FF StrictConcurrency in Swift 6? There must be some mechanism, even if a hack, of relaxing concurrency here.