Description
Description
We are hitting an EXC_BAD_ACCESS runtime crash in Swift.CheckedContinuation.resume(returning: __owned τ_0_0) -> () ()
when calling an @objc
async protocol method. This occurs when using the Swift 6.1 compiler and does not happen with Swift 6.0. It's reproducible only when there are both Swift 5 and Swift 6 language mode dependencies that include such protocols and the methods have the same return type.
Reproduction
Repro steps:
Build and run the attached sample app with Xcode 16.3
RESULT: app crashes
We narrowed down the repro to a small project with 3 targets:
Static library compiled with Swift 5 language mode:
@objc
public protocol P5 {
// This method's return type must match the return type of doSomethingElse() in P6.
// Otherwise, no crash.
func doSomething() async
}
public class Impl5: P5 {
public init() {}
public func doSomething() async {}
}
public class Swift5Class {
public init() {}
public func foo() async throws {
let p: P5 = Impl5()
await p.doSomething()
}
}
Similar static library but compiled with Swift 6 language mode:
@objc
public protocol P6 {
// This method's return type must match the return type of doSomething() in P5.
// Otherwise, no crash.
func doSomethingElse() async
}
public class Impl6: P6 {
public init() {}
public func doSomethingElse() async {}
}
public class Swift6Class {
public init() {}
public func bar() async throws {
let p: P6 = Impl6()
await p.doSomethingElse()
}
}
App target that links in the above 2 libraries:
import S5
import S6
@main
struct SampleApp {
static func main() async throws {
print("Starting call to Swift 5 class")
let s5 = Swift5Class()
try? await s5.foo()
// Crash before reaching next line.
print("Finished call to Swift 5 class")
// No crash if the next line is commented out.
let _ = Swift6Class()
}
}
Observations:
- no crash when the same code is built with Swift 6.0
- annotating the protocols as
Sendable
and making the classes final did not eliminate the crash - the language mode of the app target does not matter. It crashes whether it's built with Swift 5 or Swift 6
- no crash if the 2 libraries are both built with the same language mode
- no crash if we use the implementation directly instead of calling through the protocol, ie:
await Impl().doSomething() // no crash
- the location of the protocol definitions and class implementations does not matter. The crash still happens even if there is a single protocol and impl defined in a shared library. What matters is that the calls to the protocol methods are in 2 different targets with different language modes.
Stack dump
Thread 3 Queue : com.apple.root.default-qos.cooperative (concurrent)
#0 0x00000001959b6c90 in swift_retain ()
#1 0x000000024a2d3074 in Swift.CheckedContinuation.resume(returning: __owned τ_0_0) -> () ()
#2 0x0000000104d5f958 in _resumeCheckedContinuation<()>(_:_:) ()
#3 0x0000000104d5f828 in @objc completion handler block implementation for @escaping @callee_unowned @convention(block) () -> () with result type () ()
#4 0x0000000104d60530 in @objc closure #1 in Impl5.doSomething() ()
#5 0x0000000104d60638 in partial apply for @objc closure #1 in Impl5.doSomething() ()
#6 0x0000000104d5fab4 in thunk for @escaping @callee_guaranteed @Sendable @async () -> () ()
#7 0x0000000104d5fc10 in partial apply for thunk for @escaping @callee_guaranteed @Sendable @async () -> () ()
#8 0x0000000104d5fcec in thunk for @escaping @isolated(any) @callee_guaranteed @async () -> () ()
#9 0x0000000104d5fe50 in partial apply for thunk for @escaping @isolated(any) @callee_guaranteed @async () -> () ()
#10 0x0000000104d601a0 in specialized thunk for @escaping @isolated(any) @callee_guaranteed @async () -> (@out A) ()
#11 0x0000000104d602e8 in partial apply for specialized thunk for @escaping @isolated(any) @callee_guaranteed @async () -> (@out A) ()
Expected behavior
No crash should occur
Environment
swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
Target: arm64-apple-macosx15.0
Additional information
Swift forums post: https://forums.swift.org/t/xcode-16-3-unsafecontinuation-resume-exc-bad-access-crash/79821