What is the Never return type?

前端 未结 4 1466
我在风中等你
我在风中等你 2021-01-01 10:36

What does a func with return type Never do?

For example:

func addNums() -> Nev         


        
4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-01 10:56

    Never return type was introduced in Swift 3 to substitute @noreturn key.

    See justification in this proposal:
    SE-0102 Remove @noreturn attribute and introduce an empty Never type

    As official documentation explains:

    The return type of functions that do not return normally; a type with no values.

    Use Never as the return type when declaring a closure, function, or method that unconditionally throws an error, traps, or otherwise does not terminate.

    Source: https://developer.apple.com/documentation/swift/never

    Basic illustration:

    // The following function is our custom function we would use
    // to manually and purposefully trigger crash. In the logs,
    // we can specify what exactly went wrong: e.g. couldn't cast something, 
    // couldn't call something or some value doesn't exist:
    func crashApp() -> Never {
        fatalError("Something very, very bad happened! Crash the app!")
    }
    

    Usage specifics and advantages over @noreturn, as referenced by Erica Sadun:

    • Never allows a function or method to throw: e.g. () throws -> Never. Throwing allows a secondary path for error remediation, even in functions that were not expected to return.
    • As a first class type, Never works with generics in a way that the @noreturn attribute could not.
    • Never proactively prevents a function from claiming both a return type and no-return at the same time. This was a potential issue under the old system.

    First note (regarding secondary error remediation) is probably particularly important. Never function can have complex logic and throw – not necessarily crash.

    Let's see some interesting use cases and comparison between Never and Void

    Never

    Example 1

    func noReturn() -> Never {
        fatalError() // fatalError also returns Never, so no need to `return`
    }
    
    func pickPositiveNumber(below limit: Int) -> Int {
        guard limit >= 1 else {
            noReturn()
            // No need to exit guarded scope after noReturn
        }
        return rand(limit)
    }
    

    Example 2

    func foo() {
        abort()
        print("Should not reach here") // Warning for this line
    }
    

    Example 3

    func bar() -> Int {
        if true {
            abort() // No warning and no compiler error, because abort() terminates it.
        } else {
            return 1
        }
    }
    

    abort() is defined as:

    public func abort() -> Never
    

    Void

    These examples would not have been possible with it returning Void:

    public func abortVoid() -> Void {
        fatalError()
    }
    
    func bar() -> Int {
        if true {
            abortVoid() // ERROR: Missing return in a function expected to return 'Int'
        } else {
            return 1
        }
    }
    

    And to pack it up with abort() returning Never:

    func bar() -> Int {
        if true {
            abort() // No ERROR, but compiler sees it returns Never and warns:
            return 2 // Will never be executed
        } else {
            return 1
        }
    }
    

    We use Void to tell compiler there is no return value. Application keeps running.

    We use Never to tell compiler there is no return to caller site. Application runloop is terminated.

提交回复
热议问题