Changes in the unsafe keyword between Swift 6.3 and 6.4?

While trying to use Xcode 27, I received compiler errors related to the unsafe keyword being unnecessary. Removing the keyword addressed the error, but when the same package was then built in Xcode 26, an error was generated saying that the keyword unsafe was missing. This makes it difficult to interchangeably use Xcode 26 and 27, while preparing for macOS 27.

Package.swift:

// swift-tools-version: 6.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let swiftSettings: [SwiftSetting] = [
  .swiftLanguageMode(.v6),
  .defaultIsolation(nil),
  .strictMemorySafety(),
  .treatAllWarnings(as: .error),
  
  .enableUpcomingFeature("ExistentialAny"),
  .enableUpcomingFeature("InternalImportsByDefault"),
  .enableUpcomingFeature("MemberImportVisibility"),
  .enableUpcomingFeature("InferIsolatedConformances"),
  .enableUpcomingFeature("NonisolatedNonsendingByDefault"),
  .enableUpcomingFeature("ImmutableWeakCaptures")
]


let package = Package(
  name: "Unsafety",
  products: [.library(name: "Unsafety", targets: ["Unsafety"])],
  targets: [.target(name: "Unsafety", swiftSettings: swiftSettings)]
)

Under Xcode 27.0 beta 2 (27A5209h)

public func hello() {
  let str = "Hello World"
  unsafe str.withCString { ptr in /* some code */ }
}

Error: 
Unsafety.swift:3:3: No unsafe operations occur within 'unsafe' expression

Under Xcode 26.6 (17F113)

public func hello() {
  let str = "Hello World"
  str.withCString { ptr in /* some code */ }
}

Error:
Expression uses unsafe constructs but is not marked with 'unsafe'

Is this an expected change and is there a workaround that let's us continue to build in both toolchains?

Is it possible for a (freestanding) macro to evaluate to no tokens? If so, you could make an #unsafe macro.

Title

Potential regression in Swift 6.3 strict memory safety diagnostics for withCString

Environment- Xcode 27.0 beta 2 (27A5209h)

  • Swift 6.3
  • swift-tools-version: 6.3

For comparison:

  • Xcode 26.6 (17F113)
  • Swift 6.2

Minimal Reproducer### Package.swift

*// swift-tools-version: 6.3*

import PackageDescription

let swiftSettings: [SwiftSetting] = [
    .swiftLanguageMode(.v6),
    .defaultIsolation(nil),
    .strictMemorySafety(),
    .treatAllWarnings(as: .error),

    .enableUpcomingFeature("ExistentialAny"),
    .enableUpcomingFeature("InternalImportsByDefault"),
    .enableUpcomingFeature("MemberImportVisibility"),
    .enableUpcomingFeature("InferIsolatedConformances"),
    .enableUpcomingFeature("NonisolatedNonsendingByDefault"),
    .enableUpcomingFeature("ImmutableWeakCaptures")
]

let package = Package(
    name: "Unsafety",
    products: [
        .library(name: "Unsafety", targets: ["Unsafety"])
    ],
    targets: [
        .target(
            name: "Unsafety",
            swiftSettings: swiftSettings
        )
    ]
)

Unsafety.swift

public func hello() {
    let str = "Hello World"

    unsafe str.withCString { ptr in
        _ = ptr
    }
}

Diagnostics### Xcode 27 beta 2

No unsafe operations occur within 'unsafe' expression

If unsafe is removed:

public func hello() {
    let str = "Hello World"

    str.withCString { ptr in
        _ = ptr
    }
}

Xcode 26.6

Expression uses unsafe constructs but is not marked with 'unsafe'

Expected Behavior

The diagnostics appear contradictory between toolchains.

Either:

  1. withCString is considered an unsafe operation and should consistently require an unsafe region, or
  2. withCString is considered memory-safe, in which case older toolchains should not require unsafe.

If Swift 6.3 intentionally changes the language semantics, guidance on migrating code would be helpful.

Additional Observation

It appears that Swift 6.3 may now associate unsafe only with actual pointer dereferencing or raw pointer manipulation performed inside the closure, rather than with the call to withCString itself.

If this is the intended direction of the language, it would be useful to clarify:

  • Which standard library APIs no longer require an unsafe region.
  • Which pointer operations continue to require unsafe.
  • Whether this change is source-breaking or expected to be handled automatically by the migrator.

Question

Is this an intentional change to Swift’s strict memory safety model in Swift 6.3, or is this a compiler regression in Xcode 27 beta 2?

If intentional, is there a recommended pattern for writing source that compiles cleanly on both Swift 6.2 and Swift 6.3?

Impact

This affects libraries enabling:

  • Swift 6 language mode
  • Strict Memory Safety
  • Warnings treated as errors

because the same source currently produces mutually exclusive diagnostics on Xcode 26.6 and Xcode 27 beta 2, making it difficult to maintain compatibility across toolchains.