Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Never return type?

Tags:

types

swift

What does a func with return type Never do?

For example:

func addNums() -> Never {      //my code  } 

What will be the difference if I kept the return type as Void like this?

func addNums() -> Void {      //my code  } 

Suppose I wish to handle a fatalError (as said by dpassage); the below code will be sufficient:

print("its an error") return 

Apple documentation says:

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

Source: Developer

This was not a duplicate question of When and how to use @noreturn attribute in Swift?, as I wish for a more detailed answer which needs details like:

  1. Practical examples on the difference between both Never and Void as return types

  2. Condition by which we should adopt these return types.

  3. Also there is a chance the return type can be nil; I need a comparison of that feature too

The answer should focus on the differences.

like image 775
Saranjith Avatar asked Oct 24 '17 05:10

Saranjith


People also ask

What is never return type in Swift?

The Never return type is a special one in Swift, and tells the compiler that execution will never return when this function is called. It's used by Swift's fatalError() and preconditionFailure() functions, both of which cause your app to crash if they are called.

What is not return type?

No, constructor does not have any return type in Java. Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. Mostly it is used to instantiate the instance variables of a class.

Can we make instance of Never?

Never , on the other hand, can't do this because it can't be instantiated. When it's used to define a function or variable, or more practically, to name a generic type, it can make code impossible to run.

What does return type mean?

In computer programming, the return type (or result type) defines and constrains the data type of the value returned from a subroutine or method. In many programming languages (especially statically-typed programming languages such as C, C++, Java) the return type must be explicitly specified when declaring a function.


1 Answers

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.

like image 178
Hexfire Avatar answered Nov 12 '22 03:11

Hexfire