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

Alex Popov hello at alexpopov.ca
Fri Dec 18 12:29:02 CST 2015


Hi all,

  

I am very much pro this addition, if for nothing else than more information
for the developer using the API.

  

Limiting `throws MyErrorType` to only Enums, Structs and final Classes gets
around the Java problems so far as I can see.

  

As for the usefulness of this, I'm working on a fairly large project, and the
only way of documenting what errors can be thrown is through documentation
comments, which must then be maintained — there is little worse than incorrect
/out-of-date documentation. Although currently the catch-all is mandated,
guaranteeing safety, as a developer I'm equally concerned about recovering
from an error: without knowing exactly which Enum can be thrown, or what
subset of cases can occur, I either have to navigate to the source code and go
down the rabbit hole of tracking that information down, or just accepting that
I don't know what'll be thrown (and thereby potentially not recovering from a
recoverable failure).

  

I find it really frustrating that the compiler is unable to help me out with
this, even though in certain cases I _can_ guarantee what will be thrown. If
this proposal also brings about more convenient pattern matching for error
handling, that's a +2 from me.

  

<br  
—

<br  

Alex Popov Jr.

Principal iOS Developer | Shelfie

> On Dec 18 2015, at 9:42 am, Matthew Johnson via swift-evolution &lt;swift-
evolution at swift.org&gt; wrote:  
  

>

>> On Dec 18, 2015, at 10:50 AM, David Owens II
&lt;[david at owensd.io](mailto:david at owensd.io)&gt; wrote:

>>

>>  

>>

>>  

>>

>>> On Dec 18, 2015, at 5:53 AM, Matthew Johnson
&lt;[matthew at anandabits.com](mailto:matthew at anandabits.com)&gt; 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) -&gt; 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>.

>

>  

>

> 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

>

>  

>

> ![](https://u2002410.ct.sendgrid.net/wf/open?upn=CmwAv3oRa0AH4Hd1bWC6X-
2BzbhPqo1YEo6mPHEujr90vUljsud-2BB6KUDP5cz-
2Fv0xXzcKh2I7l3AVBGsasABqpSVQZA47MBrZnIRbuczKfFabYpw7SI-2FEE3vWg8ZsRzYrusFrkP3
-2Fdfov48EZIMr1UIxRUjZjSkWFw5gJSpy8pL-2Fo1jlRzHx1-2B7tEBTDx1EdAI9LfCCL-
2FD4vOGJSJXCTPis0shiFWB5ZEKHAD1LQ3af20-3D)

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


More information about the swift-evolution mailing list