[swift-evolution] Proposal: Allow Type Annotations on Throws

Matthew Johnson matthew at anandabits.com
Fri Dec 18 11:41:54 CST 2015


> On Dec 18, 2015, at 10:50 AM, David Owens II <david at owensd.io> wrote:
> 
> 
>> On Dec 18, 2015, at 5:53 AM, Matthew Johnson <matthew at anandabits.com> wrote:
>> 
>> David,
>> 
>> Thank you for taking the time to continue working on a proposal for typed throws.  I agree that this feature is very desirable and appreciate the work you’re doing to bring forward a proposal.  I think it’s a great start but also has some room for improvement.
>> 
>> First, I think it could be strengthened by incorporating some learning from Rust.  My impression is that the Rust community is very happy with typed error handling.  Adding some detail about their experience would provide a counter-example to those who are concerned about the experience in Java and C++.
> 
> I’m not involved in the Rust community so I wouldn’t feel comfortable making claims for them. 

I’m not asking for you to speak for them.  But I do think we need to learn from communities that are having success with typed error handling.  Your proposal would be stronger if it went into detail about how it would avoid the problems that have been encountered in other languages.  The experience of Rust could help to make that case as it is concrete and not hypothetical.

> 
>> I agree that error types are an important part of an API contract.  One of the big hurdles to doing this well is the need to catch errors when all that needs to be done is to wrap and rethrow them.  Ideally should not need to do this just to perform a simple type translation to map the underlying error into the type we wish to expose as part of a stable API contract.  You might want to take a look at the From mechanism Rust uses to facilitate this.  IMO a proposal for typed error handling should address this issue in some way (even if the author determines this mechanism is not necessary or a good design cannot be identified).
> 
> The From() construct seems like a map(T) -> U problem, but it seems heavily tied into the ability to create sum types. Swift doesn’t have this feature, and that feature is out-of-scope for this proposal. More on this later.

My understanding is that Rust uses static multi-dispatch to do this.  I don’t believe it has anything to do with structural sum types.  Rust error handling uses a Result type with a single error case: http://doc.rust-lang.org/book/error-handling.html <http://doc.rust-lang.org/book/error-handling.html>.

If you don’t believe a mechanism like this is necessary and don’t include one in your design it will lead to either a lot of boilerplate or avoidance of typed errors (depending on the developer).  I think you should expect a lot of complaints about this and I think it will generate a lot of -1 votes for the proposal.

> 
>> I would also like to see much more detail on why you think allowing a function to throw multiple error types is problematic.  My impression is that you have concerns from a usability point of view.  I am on the fence here to some degree, but definitely leaning in the direction that allowing a function to throw multiple error types is better.  
> 
> Sure. There’s no functionality today to auto-generate a sum type in Swift today, and that is what this request really is. If you want to return multiple return types, then you need to do exactly what Rust does and create a sum type that composes the various types of errors. This exposes the same potential fragile API surface as extending enums do. I did call this part out specifically.

How does this create a fragile API surface area?  Adding a new error type to the signature would be a breaking change to the API contract.  This is really no different than changing the type of error that can be thrown under your proposal.

> I see this functionality as a general limitation in the language. For example, errors are not the only context where you may want to return a type of A, B, or C. There have been other proposals on how we might do that in Swift. If and when it was solved in the general case for type parameters, I can’t foresee a compelling reason why it wouldn’t work in this context as well.

That makes sense in some ways, but I don’t think it’s unreasonable to ask for some analysis of whether a better design for typed errors would be possible if we had them.  IMO it’s pretty important to get the design of typed errors right if / when we add them.  If we don’t it will be considered a major mistake and will lead to a lot of less than desirable outcomes down the road.

I also think typed errors may be one of the more important use cases for structural sum types of some kind.  If we are able to show that design problems that cannot be solved without them can be solved with them that might influence whether they are added or not.  It might also influence when it makes sense to add support for typed errors to the language.

> 
>> I am willing to be convinced that a single error type is better than multiple error types but the current proposal does not provide a compelling argument in that direction.  It just says “Java checked exceptions”.  I know these have been pretty much universally considered a serious design mistake.  My impression is that there are quite a few reasons for that.  I don’t have any direct experience with Java and am not familiar with the details.  If you could elaborate on specifically why you believe allowing multiple error types was a significant contributor to the problem in a manner that indicates that they will be a problem in any language that includes them I would appreciate that.  Links would be sufficient if they are focused on answering this particular question.  
> 
> I guess I should have just specifically called this out in the proposal. It’s not because of “Java checked exceptions”, it’s because nowhere else in the language are types allowed to be essentially annotated in a sum-like fashion. We can’t directly say a function returns an Int or a String. We can’t say a parameter can take an Int or a Double. Similarly, I propose we can’t say a function can return an error A or B.
> 
> Thus, the primary reason is about type-system consistency.
> 
> Swift already supports a construct to create sum types: associated enums. What it doesn’t allow is the ability to create them in a syntactic shorthand. In this way, my error proposal does the same thing as Rust: multiple return types need to be combined into a single-type - enum.

That approach would make catch clauses rather clunky by nesting errors inside of associated values.  If you’re advocating for this approach do you have any ideas on how to streamline syntax for catching them?

Matthew

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151218/e53a8a51/attachment.html>


More information about the swift-evolution mailing list