Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Swift 6 Brings New Opt-In Data-Race Safe Mode

Swift 6 Brings New Opt-In Data-Race Safe Mode

In his WWDC 2024 talk, Apple's Languages and Runtimes team lead and Swift core team member Ted Kremenek introduced Swift 6 new data-race safe mode, which promises to help developers create concurrent programs free of data races thanks to a new compile-time static detector.

As Kremenek explains, the road to data-race safety has been paved across several Swift versions, starting with the introduction of async/await and Actors in Swift 5.5, sendable distributed actors in Swift 5.6, custom executors and isolation assertions in Swift 5.9, and finally, full-data isolation and isolated globals in Swift 5.10.

All those features come together in a new opt-in compiler mode that enables full data-race safety. Swift 6 makes concurrent programming dramatically easier, says Kremenek, by identifying data-race conditions at compile time to prevent different parts of the code from accessing and modifying shared data.

The reason for this new mode being opt-in is that data-race safety may require changes to existing code— albeit in many cases they will be "narrow", says Kremenek —so developers can decide when it is best to enable the new mode to tackle any data-race issues their code might have.

Alternatively, developers can opt-in to the new mode on a per-module basis, which is possible by enabling the compiler’s actor isolation and Sendable checking as warnings while still using the Swift 5 language mode.

Apple also provided a few guidelines to help developers through the process of migrating an existing project to Swift 6 and deal in an orderly way with the seemingly huge amount of warnings that the compiler may generate.

The main idea is to migrate modules one by one, starting with those that are less depended upon by other modules. This will make most of the required changes local to the module. Another useful criterion for selecting which modules to start with is considering whether any modules include unsafe global state or trivially-Sendable types, since those can cause many warnings across a project.

If the number of warnings is still too high to be tackled comfortably, the Swift compiler provides three finer-grained switches to focus on specific types of problems. You can enable them one at a time as a progressive path towards enabling complete concurrency checking. They include removing Actor Isolation Inference caused by Property Wrappers, applying strict concurrency for global variables, and inferring Sendable for methods and key path literals.

While it is well understood how global variables may be a cause of problems in a concurrent context, the other two compiler options address subtler behaviors that are specific to Swift. In particular, property wrappers may change how the Swift compiler infers isolation for the container class in a rather opaque way to the developer and this would bring unexpected potential issues (or warnings, when the static checker is enabled). Similarly, inferring sendability for partial and unapplied methods, as well as key path literals, addresses a few corner cases. You can get the full discussion in the linked Swift Evolution Proposals.

As a final note, if your Swift codebase is not yet up-to-date with the concurrency features brought by the latest language releases, now is the time to start using them. Apple suggests adopting advanced concurrency support incrementally, starting with wrapping callback-based functions to make them directly usable from an async context, adopting isolation for your classes temporarily using internal-only isolation, and so on.

About the Author

Rate this Article