3
votes

See this error:

enum MyError: ErrorType {
    case Foo
    case Bar
}

func couldThrow(string: String) throws {
    if string == "foo" {
        throw MyError.Foo
    } else if string == "bar" {
        throw MyError.Bar
    }
}

func asdf() {
    do {
        //Error: Errors thrown from here are not handled
        //because the enclosing catch is not exhaustive.
        try couldThrow("foo")
    } catch MyError.Foo {
        print("foo")
    } catch MyError.Bar {
        print("bar")
    }
}

Yet my catches cover all the possibilities. Why doesn't Swift "deeply" analyze all the possibilities and tell me nothing is wrong?

For instance, search for "catch VendingMachineError.InvalidSelection" here: https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID508

You will see in there that Apple is doing it my way. Is their code wrong?

2

2 Answers

4
votes

It's very hard for the compiler to know exactly which exceptions a piece of code could result in, because any exceptions which aren't handled at a deeper level are propagated up. While your situation is relatively simple it's generically a very difficult problem.

Note that nowhere does the code say which exceptions it can throw, only that it can throw something...

Key statement:

For example, the following code handles all three cases of the VendingMachineError enumeration, but all other errors have to be handled by its surrounding scope

So, in their example, though they don't show it, the container for that piece of code must also be capable of throwing. This is because it doesn't handle all possible exceptions.

For your case, asdf needs to be defined throws or it needs a catch all.

1
votes

Although Wain's answer is correct, there is another way to eliminate the error: use try! to treat any unhandled errors as fatal runtime errors.

func asdf() {
    try! {
        do {
            //Error: Errors thrown from here are not handled
            //because the enclosing catch is not exhaustive.
            try couldThrow("foo")
        } catch MyError.Foo {
            print("foo")
        } catch MyError.Bar {
            print("bar")
        }
    }()
}