Exhaustive catch inference

The "Error Handling" chapter of the updated Swift 2 Programming Language has the following:


"Like a

switch
statement, the compiler attempts to infer whether
catch
clauses are exhaustive. If such a determination can be made, the error is considered handled. Otherwise, the containing scope must handle the error, or the containing function must be declared with
throws
. To ensure that an error is handled, use a
catch
clause with a pattern that matches all errors."


This is followed by a code sample that (only) catches cases in a specific Error enum.


However, if I try to use this behaviour in beta 1, I always get a compile error: "Errors thrown from here are not handled because the enclosing catch is not exhaustive", UNLESS I have a catch at the end that matches any error.


Does anyone know if a) exhaustiveness inference is just not working yet, or b) catch blocks are always going to need a catch-all case at the end? If it’s the latter, the documentation is a bit misleading and the error should probably be shown on the catch, rather than the try.

It depends on the function/method that this code occurs in. If it's marked "throws" then there's no error, because the unexhausted cases are passed to the caller.


I think the example in that section is meant to be illustrative of the whole section (multiple catches), not exhaustion.

So you’re saying it’s b? Based on the phrasing in both the language guide and the compiler error, it feels to me like error type inference is either planned, or was planned and then pulled. It’s been difficult to get any clarification though - I was hoping someone here would know.

I'm saying that if the catch is in a method marked "throws" it doesn't have to be exhaustive, because the uncaught cases can propagate up to the caller.


If it's not marked "throws", then yes you need a catch-all.

My apologies, I wasn’t clear. If in a non-throwing function, is the compiler ever going to infer exhaustiveness without a catch-all? I know it doesn’t now, will it do it (where possible) in the future? It seems (to me) like it was planned at some point based on some of the language used. Or maybe I’m just reading too much into it?

I can't think of a reason to believe the compiler can ever infer exhaustiveness of implementations of ErrorType. It might be able to do so as far as your module is concerned, but surely there's always the possibility of errors from other modules, and from the runtime itself.


So it seems to me that at best the absence of 'catch {…}' could compile to a run-time check that the actual error hasn't failed to match the catches you supply. In effect, this would be a compiler-supplied catch-all-crash. (In a throwing function, this would be a compiler-supplied catch-all-rethrow.) But it seems to be against Swift's design principles to crash at places where you haven't said it could (where you haven't coded a "!").

I’m not a compiler expert, but for statically dispatched functions/methods (and possibly dynamically dispatched internal methods), I imagine the compiler should be able to determine an unambiguous list of error types generated by all throw & try statements within the function body, and associate this as hidden type information. Similar to the explicit error type annotations that everyone seems to be foolishly requesting, but automatically generated by the compiler.


There are a number of scenarios the compiler wouldn’t be able to infer (which is what I thought was meant by "the compiler attempts to infer") such as public non-final object methods, function parameters on public functions/methods, and public protocols - in this case you would still require the `catch {}`


I’m starting to think if this was ever part of the plan, the increased emphasis on protocols/protocol extensions killed it. There’s definitely a big gap left in terms of how possible error types get communicated to consumers.

>> error types generated by all throw & try statements within the function body

But there's no error type information about try statements (beyond ErrorType conformance), unless the compiler knows which override of the function will be called and it has access to the body of that function. 'final', actual or inferred, may solve the first part, but cross-module boundaries will prevent the second part

Exhaustive catch inference
 
 
Q