8

I have the following class defined on a Playground with Swift 3:

class MyError: Error {

}

Then, I create an instance of such class and check if it is a NSError

let firstError = MyError()
firstError is NSError // Output: false

The output is as expected, and I also get a warning which indicates Cast from 'MyError' to unrelated type 'NSError' always fails. This makes total sense for me, but if I change the code a little bit and declare the variable as an Error, I get a strange result:

var secondError: Error
secondError = MyError()
secondError is NSError // Output: true

And in this case I get a warning in the last line that says 'is' test is always true. I don't get why an Error would always be an NSError, when the model is defined the other way round (NSError: Error). Any idea what is going on here?

Matias
  • 541
  • 5
  • 22
  • I think this is related: http://stackoverflow.com/questions/39033194/anyobject-not-working-in-xcode8-beta6 – 0x416e746f6e Nov 30 '16 at 22:03
  • 1
    Because compiler is able to coerce `Error` to `NSError`. A quick search in Swift repo found this: https://github.com/apple/swift/blob/2fe4254cb712fa101a220f95b6ade8f99f43dc74/stdlib/public/core/ErrorType.swift#L174 – Bryan Chen Nov 30 '16 at 22:13
  • I was running into a similar issue while pattern matching NSErrors in switch statements. I found this blog post helpful: http://www.figure.ink/blog/2017/7/24/update-matching-nserrors Apparently there is some funky casting of NSError to structs, not sure if this is applicable though. – TMin Apr 04 '18 at 23:43

1 Answers1

3

This is intentional behavior to allow Swift Error types to interop with Objective-C.

The compiler will only do the coercion when bridging Swift errors to Objective-C, or in your case where all you have is the Error existential that could contain anything... remember it could just as well have come from a throws function written in Objective-C. This also gives you an out to get the coercion if you need to pass an NSError directly to some Objective-C method as a parameter (for whatever reason).

russbishop
  • 16,587
  • 7
  • 61
  • 74