[swift-evolution] typed throws
david at alkaline-solutions.com
Fri Aug 18 23:48:56 CDT 2017
> Typed throws is something we need to settle one way or the other, and I agree it would be nice to do that in the Swift 5 cycle.
> For the purposes of this sub-discussion, I think there are three kinds of code to think about:
> 1) large scale API like Cocoa which evolve (adding significant functionality) over the course of many years and can’t break clients.
> 2) the public API of shared swiftpm packages, whose lifecycle may rise and fall - being obsoleted and replaced by better packages if they encounter a design problem.
> 3) internal APIs and applications, which are easy to change because the implementations and clients of the APIs are owned by the same people.
> These each have different sorts of concerns, and we hope that something can start out as #3 but work its way up the stack gracefully.
> Here is where I think things stand on it:
> - There is consensus that untyped throws is the right thing for a large scale API like Cocoa. NSError is effectively proven here. Even if typed throws is introduced, Apple is unlikely to adopt it in their APIs for this reason.
> - There is consensus that untyped throws is the right default for people to reach for for public package (#2).
> - There is consensus that Java and other systems that encourage lists of throws error types lead to problematic APIs for a variety of reasons.
> - There is disagreement about whether internal APIs (#3) should use it. It seems perfect to be able to write exhaustive catches in this situation, since everything in knowable. OTOH, this could encourage abuse of error handling in cases where you really should return an enum instead of using throws.
> - Some people are concerned that introducing typed throws would cause people to reach for it instead of using untyped throws for public package APIs.
> - Some people think that while it might be useful in some narrow cases, the utility isn’t high enough to justify making the language more complex (complexity that would intrude on the APIs of result types, futures, etc)
I actually can’t think of anything other than details to add to this synopsis.
I personally think even for internal usage, errors remain very hard to neatly categorize into an ontology, and it is very difficult to have a single ontology for all usage. For internal usage, you at least have the ability to evolve your usage when you discover the problems, but the weight of typed throws as part of function/method types doesn’t seem worth a compiler-enforced exhaustive catch to me.
Attempting to categorize errors using a concrete error type can’t help but push the complexity of errors down via nested errors (e.g. “The JSON failed to parse - but was it due to data corruption, or transient network failure?”). Java’s multi-page nested exception traces are a side effect of attempting to corral exceptional cases using the type system - I think Swift has benefit of retroactive protocol conformance which would keep it from getting Java-level bad (see jgroff’s example), but I still don’t think people who want clear documentation or exhaustive catches want to have to dive through a hierarchy of nested errors to try to determine the root cause.
More information about the swift-evolution