Convincing Swift that a function will never return, due to a thrown Exception Convincing Swift that a function will never return, due to a thrown Exception swift swift

Convincing Swift that a function will never return, due to a thrown Exception


Swift's @noreturn attribute marks functions and methods as not returning to their caller.

As probably the simplest example, the signature of the built-in function abort()'s is:

@noreturn func abort()

This gives the compiler all the information it needs. For example, the following will compile just fine:

func alwaysFail() -> Int {    abort()}

Although alwaysFail() theoretically returns an Int, Swift knows that execution can't continue after abort() is called.

The reason my original code didn't work is because NSException.raise is a pre-Swift method, and therefore doesn't have the @noreturn attribute. To easily solve this, I can either use abort():

func shouldBeOverridden() -> ReturnType {    println("Subclass has not implemented abstract method `shouldBeOverridden`!")    abort()}

or, if I still want to use NSException, I can define an extension with the proper attribute

extension NSException {    @noreturn func noReturnRaise() {        self.raise()        abort() // This will never run, but Swift will complain that the function isn't really @noreturn if I don't call a @noreturn function before execution finishes.    }}

As a third option, I can just use a never-called abort() after an NSException.raise() to placate the compiler. The earlier option, using an extension, is really just an abstraction for doing this:

func shouldBeOverridden() -> ReturnType {    let exception = NSException(        name: "Not implemented!",        reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()",        userInfo: nil    )    exception.raise()    abort() // never called}


In Xcode 8 beta 6 (Swift 3 beta 6) you can now use the Never return type instead of @noreturn to indicate that a function won't return to its caller:

func crash() -> Never {    fatalError("Oops")}


It sounds like what you're doing would be better accomplished by creating a protocol and making shouldBeOverridden a required method, then having your classes conform to that protocol. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html