Is this a valid warning?

I sometimes add a temporary fatalError() that let's me compile a program without having completely written that function/method, ie:

func f(_ v: Int) -> Int {
    fatalError() // <-- Will allow this function to compile even though I haven't finished writing it.
}

That's how I've ran into and been a bit annoyed by this warning:

func f(_ v: Int) -> Int { // WARNING: All paths through this function will call itself
    if v > 0 { return f(v - 1) }
    fatalError("Not fully implemented")
}

Should that warning really be there?

It seems to me like that statement is not true, because it misses the trapping path.

(cc @codafi, @harlanhaskins)

Too many people use fatalError() to indicate a condition that cannot occur. If the warning didn't ignore paths ending in fatalError(), it would miss a whole ton of useful cases.

2 Likes

To give a little more detail, what you're seeing in Swift 4.2 is actually a false positive. The infinite recursion pass didn't consider unreachable instructions as "function exiting", which also means you'd see a warning if you wrote:

func f(_ v: Int) -> Int { // warning: All paths through this function will call itself
    if v > 0 { return f(v - 1) }
    exit(0)
}

In Swift 5, we fixed the false positive, but we intentionally left fatalError, assertionFailure, and preconditionFailure (and anything else marked with @_semantics("programtermination_point") to still warn. This is because, as Jordan said, you really never want that code to be called, so you wouldn't want to consider it part of your regular control flow.

6 Likes

Is the warning gone from the following example in Swift 5?

func fatalToDo() -> Never {
    fatalError()
}

func f(_ v: Int) -> Int { // WARNING: All paths through this function will call itself
    if v > 0 { return f(v - 1) }
    fatalToDo()
}

Nope, specifically because fatalError is not considered part of the intended control flow

Sorry, I misread your example. Yes, normal -> Never functions silence the warning, and the analysis does not look through function calls.

1 Like