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.
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.
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.
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()
}