What is "Swift 6 mode"?
Swift 6 won't be released in 2023 anymore, that has been made clear by Doug Gregor from the Swift Language Workgroup. But did you know that Apple has already shipped parts of Swift 6 in 5.8? Yes, it's true. Some parts of Swift that shipped with Xcode 14.3 a few weeks ago are turned off by default. They will be turned on once Swift 6 comes out, which might take another year, or even longer.
These features introduce some breaking changes to Swift, for example by renaming known APIs, adjusting their behavior, or adding new safety checks to the compiler. But they will all get turned on at some point to help improve our code bases. And we will have to update our projects to play nicely with those changes.
I figured it's a good idea to turn on all features in my projects to see if there's any breaking change for my codebase that I should know of. And of course, I could also make use of some new features, such as
BareSlashRegexLiterals, which makes the
/.../ regex literal syntax available for concise Regex initialization.
Thankfully, with Swift 5.8 there's now a unified way of enabling these options: We just need to pass
-enable-upcoming-feature to Swift by providing it in the
OTHER_SWIFT_FLAGS in our projects build settings in Xcode. But we need to know also what features are available, and I couldn't find any place with a good overview (yet). The proposal that introduced this unified option does contain such a list, but it doesn't get updated with newer options added later on, such as the one from SE-0384. So, where can we currently reliably get a list of all supported options?
Swift is open source, so the most reliable place seems the Swift GitHub repository! It includes a
Features.def file which contains entries (link to
release/5.8 branch) named
UPCOMING_FEATURE including both the related Swift Evolution proposal number and the Swift version they will be turned on:
UPCOMING_FEATURE(ConciseMagicFile, 274, 6) UPCOMING_FEATURE(ForwardTrailingClosures, 286, 6) UPCOMING_FEATURE(BareSlashRegexLiterals, 354, 6) UPCOMING_FEATURE(ExistentialAny, 335, 6)
Here are the options with a short description of what they do:
Removes the backward-scan matching rule.
anyfor existential types.
/.../regex literal syntax available.
For some reason, two options seem not to be listed there (I'm investigating):
Performing complete concurrency checking.
Performs implicit opening in additional cases.
More options will ship with later versions, e.g.
To additionally check my code for proper concurrency support, I chose to also pass
-warn-concurrency (this should actually be the same as
StrictConcurrency if that actually works) and
Migrating my project
If you also want to enable all
5.8 options in your project, like me, copy (⌘C) the following text block, then head to your Xcode projects "Build Settings" tab, search for "Other Swift Flags", select that option in the editor and paste (⌘V) it in:
//:configuration = Debug OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks //:configuration = Release OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks //:completeSettings = some OTHER_SWIFT_FLAGS
If you are using a SwiftPM-modularized app like me, or if you're working on a Swift package, you will need to additionally pass an array of
.enableUpcomingFeature's to each target via
let swiftSettings: [SwiftSetting] = [ .enableUpcomingFeature("BareSlashRegexLiterals"), .enableUpcomingFeature("ConciseMagicFile"), .enableUpcomingFeature("ExistentialAny"), .enableUpcomingFeature("ForwardTrailingClosures"), .enableUpcomingFeature("ImplicitOpenExistentials"), .enableUpcomingFeature("StrictConcurrency"), .unsafeFlags(["-warn-concurrency", "-enable-actor-data-race-checks"]), ] let package = Package( // ... targets: [ // ... .target( name: "MyTarget", dependencies: [/* ... */], swiftSettings: swiftSettings ), // ... ]
Don't forget to upgrade your tools version at the top of the file to
That's because Swift doesn't pass along the options you specified for your project target automatically to any modules you import into your project. And that's good news, because that way Swift packages you might be including into your project don't need any adjustments and you can still use these features for your own app code. And vice versa: Package authors can turn these features on for their projects without affecting the code in projects they get consumed in.
After turning these on and building, I ran into four kinds of issues:
1. I had to add the
any keyword in several places – Xcode helped with a Fix-It:
2. For some reason I received a lot of errors for views with a
.sheet modifier. The error pairs stated: "Generic parameter 'Content' could not be inferred" and "Missing argument for parameter 'content' in call". These messages weren't very helpful though, so I first tried to replace the
.sheet content with just a
Text view, but it didn't help. So I've tried turning off the options one by one and the errors disappeared when I turned off
ForwardTrailingClosures, so I kept it turned off. I'm hoping that a better error message will be produced by future versions of Swift to fix them later. There's no hurry, after all. I can retry on Swift 5.9. I didn't have time to investigate now.
3. I had to mark some of my functions returning a TCA
WithViewStore with the
@MainActor attribute, but again, Xcode helped with Fix-Its.
4. In many places, warnings were shown stating: "Non-sendable type '...' passed in call to main actor-isolated function cannot cross actor boundary". So I made these types conform to the
Sendable protocol (learn about
All else seemed to build fine for my app RemafoX with ~35k lines of Swift code. The whole process took less than 3 hours of my time.
My project is now ready for the future of Swift 🎉 and I can use the new Regex literal feature (
let regex = /.*@.*/). Also, I can't introduce new code that I have to migrate to Swift 6 later, cause I will receive errors right away. 💯
How about your project? Which upcoming features do you want to migrate to?
A native Mac app that integrates with Xcode to help translate your app.
Get it now to save time during development & make localization easy.