I totally forgot I promised to post about Never
. So first some apology Elvis. And that done, let me introduce you to this new Swift 3 keyword.
SE-0102 removes the rarely-used @noreturn
function type and replaced it with a dead-end return type:
/// The type of expressions that can never happen. public /*closed*/ enum Never { /*no values*/ } func foo() -> Never { fatalError("no way out!") }
Using Never
allows you to express the condition where a method or function, whether by dispatch (completion handlers, for example, although you generally don’t need Never
for that use-case) or expected exit (for example, a usage()
function in a command-line Swift app) will never return control back to the call site.
I haven’t used Never
very much. To date, it’s mostly a command line thing for me, and one where I’m more testing the waters than using confident assurance.
// Fetch arguments and test for usage var arguments = CommandLine.arguments let appName = arguments.remove(at: 0).lastPathComponent func usage() -> Never { print("Usage: \(appName) location1 location2"); exit(-1) } guard arguments.count == 2 else { usage() }
The Swift compiler picks up the Never
return type in the guard statement, accepting that the else clause leaves scope.
According to Joe Groff’s proposal, there are several advantages of using Never
over @noreturn.
Never
allows a function or method tothrow
: 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.
Joe writes in summary: “The net result is a simpler, more consistent, and more expressive model for handling nonreturning functions.”
3 Comments
I tried using Never for my API module callbacks but couldn’t really figure out how to use it when my callbacks contains guards.
Example
Do you have any hints on how to properly use Never for such case.
It makes more sense when the completion handler will end the app, no? Quick answer (really deserves its own post):
Yeah so to me it doesn’t seem suitable for completion blocks in my case.
Sad, I wished it was what I was looking for. I’ll stick with my returns in guards for now I guess ????