Building a Swift package using the Swift 6 language mode

Sponsored
RevenueCat logo
Relax, you can roll back your mobile release

No one is immune from shipping critical bugs to production, but Runway helps you limit the amount of havoc that can cause.

I have recently learned that some of the breaking changes that will come with Swift 6 (like full data isolation and data race safety checks) will be part of the Swift 6 language mode, which will be an opt-in feature in the Swift 6 compiler.

This means that, when you update your version of Xcode or use a Swift toolchain that uses the Swift 6 compiler, unless you explicitly enable the Swift 6 language mode, your code will be compiled using the Swift 5 language mode.

In this article, I will show you how to download and install a development snapshot of the Swift 6 toolchain and enable the Swift 6 language mode when building a Swift package.

Downloading a Swift 6 toolchain

The first step to building your code with the Swift 6 compiler and language mode is to download a Swift 6 development toolchain.

Apple makes builds of the Swift compiler from the release/6.0 branch available for numerous platforms on the swift.org website that you can download and install on your system.

You can choose to do this manually, but I would recommend using a tool like Swiftenv for macOS or Swiftly for Linux to manage your Swift toolchains, as I am going to do in this article.

SwiftEnv - macOS

Swiftenv is a Swift version manager inspired by pyenv that allows you to easily install and manage multiple versions of Swift.

Using Swiftenv, installing the latest Swift 6 development snapshot is as easy as running the following commands:

Terminal
# Install the latest Swift 6 development toolchain
swiftenv install 6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a

# CD into your Swift package directory
cd your-swift-package

# Set the Swift 6 toolchain as the default for this directory
swiftenv local 6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a

Swiftly - Linux

If you’re trying to build your code on a Linux machine, you can use the Swift Server Workgroup’s Swiftly command line tool to install and manage Swift toolchains by running the following commands:

Terminal
# Install the latest Swift 6 development toolchain
swiftly install 6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a

# Set the Swift 6 toolchain as the active toolchain
swiftly use 6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a

Turning the language mode on in SPM

Let’s consider a Swift package target with some code that yields an error when compiled using the Swift 6 compiler and the Swift 6 language mode:

ErrorOnSwift6.swift
class NonIsolated {
    func callee() async {}
}

actor Isolated {
    let isolated = NonIsolated()
    
    func callee() async {
        await isolated.callee()
    }
}

Let’s build it using the Swift 6 toolchain we downloaded earlier and with the StrictConcurrency experimental feature turned on:

As you can see, the result of the build is a warning instead of an error. This is because, by default, the Swift 6 compiler uses the Swift 5 language mode and the Swift 6 language mode is opt-in.

There are two ways to enable the Swift 6 language mode: directly from the command line by passing the -swift-version flag to the swift compiler or by specifying it in the package manifest file.

Command line

To build your code with the Swift 6 language mode enabled, you can use the following command:

Terminal
swift build -Xswiftc -swift-version -Xswiftc 6

Package manifest

You can enable the Swift 6 language mode for your Swift Package by updating the tools-version to 6.0 and adding the swiftLanguageVersions key to the package manifest file:

Package.swift
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "Swift6Examples",
    platforms: [.macOS(.v10_15), .iOS(.v13)],
    products: [
        .library(
            name: "Swift6Examples",
            targets: ["Swift6Examples"]
        )
    ],
    targets: [
        .target(name: "Swift6Examples")
    ],
    swiftLanguageVersions: [.version("6")]
)

Output

Now, when you build your code with the Swift 6 language mode enabled, you will see that the error is correctly reported: