Issue #1050
Swift 6.4 arrives with a set of language refinements and standard library additions that make everyday code cleaner and more expressive. This article walks through the most notable changes from WWDC26.
Simplified platform availability with anyAppleOS
As Apple has aligned OS version numbers across platforms, Swift 6.4 takes the next step by letting you collapse repetitive availability attributes into a single anyAppleOS token.
// Before
@available(macOS 27, iOS 27, watchOS 27, tvOS 27, visionOS 27, *)
func showStatus() { ... }
// After
@available(anyAppleOS 27, *)
func showStatus() { ... }
When one platform needs a carve-out, combine anyAppleOS with a specific override. The same token works inside #if os(anyAppleOS) for conditional compilation.
Controlling warnings with @diagnose
There are situations where you need to call a deprecated API while you plan a migration, or audit a critical function for unsafe usage, without letting those concerns bleed into the rest of the project. The new @diagnose attribute handles both cases.
@diagnose(DeprecatedDeclaration, as: ignored, reason: "Migrating incrementally")
func makeApolloMission() -> Mission {
CrewedMission(rocket: makeSaturnIRocket(), ...)
}
You can suppress, promote to warning, or escalate to error on a per-declaration basis. This is a precise scalpel rather than a project-wide flag.
Module selectors for disambiguation
When two imported modules export the same name, Swift tries to resolve the conflict with dot syntax, but that breaks if the module itself has a type sharing its name. The new :: module selector syntax guarantees the left-hand side is always treated as a module, never a type.
import SwiftUI
import Charts
let body = SwiftUI::View.self // SwiftUI's View protocol
let chart = Charts::View.self // Charts' View type
Module selectors also work on method names, which is useful when a type inherits identically-named methods from extensions in different modules.
user.DatabaseKit::delete() // removes from local store
user.CloudSync::delete() // removes from remote
This is especially valuable in generated code, like macro expansions, where you have no control over what else is imported into a project.
Better Sendable and concurrency ergonomics
A few small concurrency annoyances are fixed in 6.4. A weak var property used to force @unchecked Sendable; it can now be written as weak let, satisfying regular Sendable checking without the escape hatch.
final class Spacecraft: Sendable {
weak let dockedAt: SpaceStation?
}
When a class should explicitly opt out of Sendable, you can state that with ~Sendable rather than leaving it implicit.
class Mission: ~Sendable { ... }
class CrewedMission: Mission, @unchecked Sendable { ... }
Calling async functions from a defer block is also now allowed, which removes a limitation that often required awkward workarounds.
let uploadTask = Task {
try await storage.upload(file)
}
defer {
await logger.flush()
}
try await uploadTask.value
More accessible memberwise initializers
A struct mixing internal and private properties now gets two generated memberwise initializers: one that includes the private properties (accessible only within the file) and one that omits them (accessible across the module). Previously you had to write the second one by hand.
struct Briefing {
internal var topic: String
internal var scheduledAt: Date
private var attendees: [Person] = []
// Swift now generates both a private full init and an internal partial init
}
Standard library additions
Task cancellation shield
Some work should complete even after a task is cancelled, like flushing a file to avoid corruption. withTaskCancellationShield wraps a region where Task.isCancelled always returns false.
extension EmergencyTransponder {
func sendSOS() {
withTaskCancellationShield {
radio.send(makeSOSPacket())
}
}
}
Keep the shielded region short and focused on rollback or completion work.
mapKeyedValues on Dictionary
The existing mapValues gives you only the value in the transform closure. The new mapKeyedValues passes both key and value.
let displayNames = missions.mapKeyedValues { mission, window in
makeDisplayName(for: mission, in: window)
}
New FilePath type
The standard library gains a FilePath type ported from Swift System. It handles platform differences in path representation correctly and parses components consistently, removing a common source of subtle bugs in cross-platform code.
var path: FilePath = "/Users/khoa/Documents"
path.components.append("Projects")
path.components.append("app")
print(path.components)
// [ "Users", "khoa", "Documents", "Projects", "app" ]
Start the conversation