Bridging to NSError fails for instances of a class

(This question is motivated by Evaluating if Error is NSError always succeeds while casting Error as NSError gives a compiler error on Stack Overflow.)

According to SE-0112, every type that conforms to the Error protocol is implicitly bridged to NSError. It seems that this does not work with reference types, the last line in the following example does not compile:

class MyError: Error {}

extension MyError: CustomNSError {
    public static var errorDomain: String { "MyDomain" }
    public var errorCode: Int { 13 }
    public var errorUserInfo: [String : Any] { ["Foo" : "Bar" ] }
}

let sError = MyError()

let nsError = sError as NSError
// error: 'MyError' is not convertible to 'NSError'; did you mean to use 'as!' to force downcast?

As forced cast (as suggested by the compiler), makes it compile with a warning:

let nsError = sError as! NSError
// warning: forced cast from 'MyError' to 'NSError' always succeeds; did you mean to use 'as'?

but crashes at runtime:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Interestingly, inserting an “intermediate cast” to Error makes it compile and run as expected:

let nsError = sError as Error as NSError
print(nsError.userInfo)
// ["Foo": "Bar"]

That problem occurs only if the custom error type is a class, not with a struct or an enum.

I wonder if this is a bug, or to be expected.

Thanks, Martin

1 Like

I have filed a bug report: SR-14322

Terms of Service

Privacy Policy

Cookie Policy