Hello there!
I've been trying to use typed throws feature for a testing (not Swift Testing) framework in our team. However I'm hitting a compiler crash when I'm using actors with generic ErrorType constraint. (With ordinary classes this is not an issue).
With Xcode 16.X I was able to work around the issue, however with the new Xcode 26 betas, it started crashing in runtime.
I have an actor like this:
// defining a typealias doesn't help, but this doesn't prevent the code from compiling in combination with case 3.
public typealias Pipeline<Input, ErrorType: Error, Output> = (Input) throws(ErrorType) -> Output
public actor ThreadSafeMockThrowingTypedErrorFunc<Input, Output, ErrorType: Swift.Error> {
private var didCall: (Input) throws(ErrorType) -> Void = { _ in }
public private(set) var invocations: [Input] = []
// case 1: this doesn't compile
// public private(set) var result: Pipeline<Input, ErrorType, Output>
// case 2: this doesn't compile, but this is the desired version
// public private(set) var result: (Input) throws(ErrorType) -> Output
// case 3: this compiles fine
public private(set) var result: (Input) throws -> Output
public var input: Input {
invocations[invocations.count - 1]
}
public var output: Output {
// if we use case 3, then here we have to `do-catch` in order to satisfy the compiler.
// the desired version of the code is in MockThrowingTypedErrorFunc.swift
// public var output: Output {
// get throws(ErrorType) {
// try result(input)
// }
// }
get throws(ErrorType) {
do {
return try result(input)
} catch let error as ErrorType { // Swift 6.2 crashes here with `Task XX: EXC_BAD_ACCESS (code=1, address=0x...)` But if I do `po error`, I get `SwiftCompilerActorAndTypedThrowsBugSampleProjectTests.ImageLoadingError.test`
throw error
} catch {
fatalError("There's a bug in the compiler that does not allow us to specify the error type in the signature of the closure (see ``result`` property) when it's used in Actor.")
}
}
}
public init(function: StaticString = #function, line: Int = #line) {
result = { _ throws(ErrorType) in
fatalError("You must provide a result handler before using MockFunc instantiated at line: \(line) of \(function)")
}
}
public func callAndReturn(_ input: Input) throws(ErrorType) -> Output {
try call(with: input)
return try output
}
public func `throws`(_ error: ErrorType) {
result = { _ throws(ErrorType) in
throw error
}
}
private func call(with input: Input) throws(ErrorType) {
invocations.append(input)
try didCall(input)
}
}
And I have a test like this:
@Test("Typed Throw is problematic with actors. It crashes!")
func threadSafeThrowingMockFuncUnhappyPth() async throws {
let sut = MockImageLoader()
await sut.loadAsyncThrowsUrlMock.throws(URLError(.badURL))
await #expect(throws: URLError(.badURL), performing: { try await sut.loadAsyncThrows(url: URL.sample) })
#expect(await sut.loadAsyncThrowsUrlMock.input == URL.sample)
}
I get a crash on this line: } catch let error as ErrorType {
It's persistent with all betas of Xcode 26.
I've put together a sample project here with the full problem:
I wonder if I'm doing something wrong or misusing the API, but the same thing works fine for classes, so I guess there's got to be something about the compiler and actors.