<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">David,<div class=""><br class=""></div><div class="">Thank you for taking the time to continue working on a proposal for typed throws. &nbsp;I agree that this feature is very desirable and appreciate the work you’re doing to bring forward a proposal. &nbsp;I think it’s a great start but also has some room for improvement.</div><div class=""><br class=""></div><div class="">First, I think it could be strengthened by incorporating some learning from Rust. &nbsp;My impression is that the Rust community is very happy with typed error handling. &nbsp;Adding some detail about their experience would provide a counter-example to those who are concerned about the experience in Java and C++.</div><div class=""><br class=""></div><div class="">I agree that error types are an important part of an API contract. &nbsp;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. &nbsp;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. &nbsp;You might want to take a look at the From mechanism Rust uses to facilitate this. &nbsp;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).</div><div class=""><br class=""></div><div class="">I would also like to see much more detail on why you think allowing a function to throw multiple error types is problematic. &nbsp;My impression is that you have concerns from a usability point of view. &nbsp;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. &nbsp;</div><div class=""><br class=""></div><div class="">The primary reason I lean this way is that it enables more re-use of standard error types. &nbsp;Custom error types for an API often make sense, but not always. &nbsp;I am concerned about the need to create them just because our API contract might reasonably include two or three of the standard error types. &nbsp;Adding new types when they are not necessary introduces complexity and cognitive overhead. &nbsp;It also complicates catching of errors if the new custom type is a two or three case enum that just embeds the underlying error. &nbsp;</div><div class=""><br class=""></div><div class="">These problems will lead many people to just revert to an untyped throws clause. &nbsp;Objections to typed errors along these lines are common and legitimate. &nbsp;They will arise during review. &nbsp;It is best if you address them in the proposal now in order to focus a review on your solutions. &nbsp;My personal opinion is that allowing multiple error types and including a mechanism to perform automatic wrapping when appropriate would go a long way towards solving them.</div><div class=""><br class=""></div><div class="">Implementation challenges related to multi-typed errors have been discussed on the list quite a bit already. &nbsp;They would obviously need to be addressed if we go in that direction. &nbsp;I don’t want to downplay those. &nbsp;But I do think we need to try to identify the most usable solution for typed errors that we can first and then focus on implementation details. &nbsp;If the design needs to be modified to accommodate implementation at least we will have a better idea of what we are giving up.</div><div class=""><br class=""></div><div class="">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. &nbsp;It just says “Java checked exceptions”. &nbsp;I know these have been pretty much universally considered a serious design mistake. &nbsp;My impression is that there are quite a few reasons for that. &nbsp;I don’t have any direct experience with Java and am not familiar with the details. &nbsp;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. &nbsp;Links would be sufficient if they are focused on answering this particular question. &nbsp;</div><div class=""><br class=""></div><div class="">I’m looking forward to your feedback on these thoughts.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Matthew</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Dec 18, 2015, at 1:29 AM, David Owens II via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">This a significantly updated proposal for typed annotations on the `throws` construct. The previous was closed due to not be complete; I believe I’ve addressed all of those concerns.<div class=""><br class=""></div><div class=""><a href="https://github.com/owensd/swift-evolution/blob/master/proposals/allow-type-annotations-on-throw.md" class="">https://github.com/owensd/swift-evolution/blob/master/proposals/allow-type-annotations-on-throw.md</a></div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class=""><h1 style="margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 28px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255); margin-top: 0px !important;" class="">Allow Type Annotation on Throws</h1><ul style="margin: 15px 0px; padding-left: 30px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class=""><li style="margin: 0px 0px 15px;" class="">Proposal:&nbsp;<a href="" style="color: rgb(65, 131, 196); margin-top: 0px; margin-bottom: 0px;" class="">SE-NNNN</a></li><li style="margin: 15px 0px;" class="">Author(s):&nbsp;<a href="" style="color: rgb(65, 131, 196); margin-top: 0px; margin-bottom: 0px;" class="">David Owens II</a></li><li style="margin: 15px 0px;" class="">Status:&nbsp;<strong style="margin-top: 0px; margin-bottom: 0px;" class="">Pending Approval for Review</strong></li><li style="margin: 15px 0px 0px;" class="">Review manager: TBD</li></ul><h2 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Introduction</h2><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The error handling system within Swift today creates an implicitly loose contract on the API. While this can be desirable in some cases, it’s certainly not desired in&nbsp;<em class="">all</em>&nbsp;cases. This proposal looks at modifying how the error handling mechanism works today by adding the ability to provide a strong API contract.</p><h2 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Error Handling State of the Union</h2><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This document will use the terminology and the premises defined in the&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst" title="Error Handling Rationale" style="color: rgb(65, 131, 196);" class="">Error Handling Rationale</a>&nbsp;document.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">To very briefly summarize, there are four basic classification of errors:</p><ol style="margin: 15px 0px; padding-left: 30px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class=""><li style="margin: 0px 0px 15px;" class="">Simple Domain Errors</li><li style="margin: 15px 0px;" class="">Recoverable Errors</li><li style="margin: 15px 0px;" class="">Universal Errors</li><li style="margin: 15px 0px 0px;" class="">Logic Failures</li></ol><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Each of these types of errors are handled differently at the call sites. Today, only the first two are directly handled by Swift error handling mechanism. The second two are uncatchable in Swift (such as&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">fatalError()</code>, ObjC exceptions, and force-unwrapping of&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">null</code>&nbsp;optionals).</p><h3 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 18px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Simple Domain Errors</h3><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">As stated in&nbsp;<a href="https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst" title="Error Handling Rationale" style="color: rgb(65, 131, 196);" class="">Error Handling Rationale</a>&nbsp;document, the “Swift way” to handle such errors is to return an&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional&lt;T&gt;</code>.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func parseInt(value: String) -&gt; Int? {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The simple fact of the result being&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional.None</code>&nbsp;signifies that the string could not be parsed and converted into an&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Int</code>. No other information is necessary or warranted.</p><h3 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 18px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Recoverable Errors</h3><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">In this context, these are errors that need to provide additional information to the caller. The caller can then decide a course of action that needs to be taken. This could be any number of things, including, but not limited to, logging error information, attempting a retry, or potentially invoking a different code path. All of these errors implement the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;protocol.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func openFile(filename: String) throws {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;keyword annotates that the function can return additional error information. The caller must also explicitly make use of this when invoking the function.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">do {
  try openFile("path/to/somewhere")
}
catch {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Errors are able to propagate if called within another context that can throw, thus alleviating the annoying “catch and rethrow” behavior:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func parent() throws {
  try openFile("path/to/somwhere")
}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Lastly, functions can be marked to selectively throw errors if they take a function parameter that throws with the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">rethrows</code>&nbsp;keyword. The really interesting part is that it’s only necessary to use&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try</code>&nbsp;when calling the function with a throwing closure.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func openFile(filename: String) throws {}
func say(message: String) {}

func sample(fn: (_: String) throws -&gt; ()) rethrows {
    try fn("hi")
}

try sample(openFile)
sample(say)
</code></pre><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Converting Recoverable Errors to Domain Errors</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Swift also has the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try?</code>&nbsp;construct. The notable thing about this construct is that it allows the caller to turn a “Recoverable Error” into a “Simple Domain Error”.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">if let result = try? openFile("") {}
</code></pre><h3 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 18px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class=""><code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">ErrorType</code>&nbsp;Implementors</h3><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Errors are implemented using the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;protocol. Since it is a protocol, new error types can be a class, a struct, or an enum. A type qualified&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;clause would allow code authors to change the way that the catch-clauses need to be structured.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Enum Based&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">ErrorType</code></h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">When enums are used as the throwing mechanism, a generic catch-clause is still required as the compiler doesn’t have enough information. This leads to ambiguous code paths.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">enum Errors: ErrorType {
    case OffBy1
    case MutatedValue
}

func f() throws { throw Errors.OffBy1 }

do {
    try f()
}
catch Errors.OffBy1 { print("increment by 1") }
catch Errors.MutatedValue { fatalError("data corrupted") }
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The above code requires a&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">catch {}</code>&nbsp;clause, but it’s ambiguous what that case should do. There is no&nbsp;<em class="">right</em>&nbsp;way to handle this error. If the error is ignored, we’re now in the land of “Logic Errors”; the code path should never be hit. If we use a&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">fatalError()</code>&nbsp;construct, then we are now in the land of converting a potential compiler error into a “Universal Error”.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Both of these are undesirable.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Struct and Class Based&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">ErrorType</code></h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">In the current design, errors that are thrown require a catch-all all the time. In the proposed design, which will be explained further, a catch-all would not be required if there was a case-clause that matched the base type.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">class ErrorOne: ErrorType {}
func g() throws { throw ErrorOne() }

do {
    try g()
}
catch is ErrorOne { print("ErrorOne") }
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The advantage in these cases are different, these cases do not allow pattern matching over the error type members (as you can in a switch-statement, for example).</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The workaround for this functionality is this:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">class ErrorOne: ErrorType {
    let value: Int
    init(_ value: Int) { self.value = value }
}

do {
    try g()
}
catch {
    if let e = error as? ErrorOne {
        switch e {
        case _ where e.value == 0: print("0")
        case _ where e.value == 1: print("1")
        default: print("nothing")
        }
    }
}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This proposal would turn the above into:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">class ErrorOne: ErrorType {
    let value: Int
    init(_ value: Int) { self.value = value }
}

do {
    try g()
}
catch _ where error.value == 0 { print("0") }
catch _ where error.value == 1 { print("1") }
catch { print("nothing") }
}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">No gymnastics to go through, just straight-forward pattern-matching like you’d expect.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">NOTE: This requires the promotion of the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>&nbsp;constant to be allowed through the entirety of the catch-clauses.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Overriding</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">In the context of types, it’s completely possible to override functions with the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;annotations. The rules simply follow the rules today: covariance on the return type is allowed, contravariance is not.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Generics</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">When looking at generics, I cannot come up with a reason why they shouldn’t just work as normal:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func gen&lt;SomeError: ErrorType&gt;() throws SomeError {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The only constraint would be that the specified error type must adhere to the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;protocol. However, this is no different than today:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func f&lt;T&gt;(a: T) throws { throw a }
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This results in the compiler error:</p><blockquote style="margin: 15px 0px; border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class=""><div style="margin: 0px;" class="">Thrown expression type ’T’ does not conform to ‘ErrorType’</div></blockquote><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This seems like it should “just work”.</p><h2 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Design Change Proposal</h2><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The design change is simple and straight-forward: allow for the annotation of the type of error that is being returned as an optional restriction. The default value would still be&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func specific() throws MyError {}
func nonspecific() throws {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">There is a secondary result of this proposal: the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>&nbsp;constant should be promoted to be allowed for use through-out all of the catch-clauses.</p><h3 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 18px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Impact on Existing Code</h3><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This is a non-breaking change. All existing constructs work today without change. That said, there are a few places where this change will have an impact on future usage.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Function Declarations</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">When a function has a&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;clause that is attributed with a type, then that type becomes part of the function signature. This means that these two functions are not considered to be of the same type:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func one() throws {}
func two() throws NumberError {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The function signatures are covariant though, so either&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">one</code>&nbsp;or&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">two</code>&nbsp;can be assigned to&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">f</code>&nbsp;below:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">let f: () throws -&gt; ()
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This is completely fine as&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">NumberError</code>&nbsp;still implements the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;protocol.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">However, in this case:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">let g: () throws NumberError -&gt; ()
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">It would not be valid to assign&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">one</code>&nbsp;to&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">g</code>&nbsp;as the type signature is more specific.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class=""><code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">throws</code>&nbsp;and&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">rethrows</code></h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Functions currently have the ability to be marked as&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">rethrows</code>. This basically says that if a closure parameter can throw, then the function will throw too.&nbsp;</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func whatever(fn: () throws -&gt; ()) rethrows {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">whatever</code>&nbsp;function is up for anything that&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">fn</code>&nbsp;is up for. Keeping in line with this mentality, the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">rethrows</code>&nbsp;would exhibit the same behavior: typed annotations simply apply if present and do not if they are missing.</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func specific(fn: () throws HappyError -&gt; ()) rethrows {}
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This all works as expected:</p><pre style="margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">func f() throws HappyError {}
func g() {}

try specific(f)
specific(g)
</code></pre><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This works for the same covariant reason as the non-qualified&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;implementation works: a non-throwing function is always able to be passed in for a throwing function.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">The&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">do</code>-<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">catch</code>&nbsp;statement</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">There are two rule changes here, but again, it’s non-breaking.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The first rule change is to promote the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>&nbsp;constant that would normally only be allowed in the catch-all clause (no patterns) to be available throughout each of the catch clauses. This allows for the error information to be used in pattern matching, which is especially valuable in the non-enum case.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The second change is to allow the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>&nbsp;constant to take on a specific type when&nbsp;<em class="">all</em>&nbsp;of the throwing functions throw the same specified type. When this is the case, two things become possible:</p><ol style="margin: 15px 0px; padding-left: 30px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class=""><li style="margin: 0px 0px 15px;" class="">In the enum-type implementation of&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>, the catch-clauses can now be exhaustive.</li><li style="margin: 15px 0px 0px;" class="">In the all of the cases, the API of the specific&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;becomes available in the catch-clause without casting the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>&nbsp;constant. This greatly simplifies the pattern-matching process.</li></ol><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">In the case that there are heterogenous&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;implementations being returned, the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">error</code>constant simply has the type of&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>.</p><h4 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 16px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">The&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-size: inherit;" class="">try</code>&nbsp;call sites</h4><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">There is no change for the&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try</code>,&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try?</code>, or&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try!</code>&nbsp;uses. The only clarification I’ll add is that&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">try?</code>is still the appropriate way to promote an error from a “Recoverable Error” to a “Simple Domain Error”.</p><h2 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Alternate Proposals</h2><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">There is another common error handling mechanism used in the community today:&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Either&lt;L, R&gt;</code>. There are various implementations, but they all basically boil down to an enum that captures the value or the error information.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">I actually consider my proposal syntactic sugar over this concept. If and when Swift supports covariant generics, there is not a significant reason I can see why the underlying implementation could not just be that.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The advantage is that the proposed (and existing) syntax of&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">throws</code>&nbsp;greatly increases the readability and understanding that this function actually possesses the ability to throw errors and they should be handled.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">The other advantage of this syntax is that it doesn’t require a new construct to force the usage of the return type.&nbsp;</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Further, if functions where to ever gain the ability to be marked as&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">async</code>, this could now be handled naturally within the compiler as the return type could a promise-like implementation for those.</p><h2 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Criticisms</h2><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">From the earlier threads on the swift-evolution mailing list, there are a few primary points of contention about this proposal.</p><h5 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 14px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Aren’t we just creating Java checked-exceptions, which we all know are terrible?</h5><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">No. The primary reason is that a function can only return a single error-type. The other major reason is that the error philosophy is very different in Swift than in Java.</p><h5 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 14px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Aren’t we creating fragile APIs that can cause breaking changes?</h5><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Potentially, yes. This depends on how the ABI is handled in Swift 3 for enums. The same problem exists today, although at a lesser extent, for any API that returns an enum today.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Chris Lattner mentioned this on the thread:</p><blockquote style="margin: 15px 0px; border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class=""><div style="margin: 0px;" class="">The resilience model addresses how the public API from a module can evolve without breaking clients (either at the source level or ABI level). &nbsp;Notably, we want the ability to be able to add enum cases to something by default, but also to allow API authors to opt into more performance/strictness by saying that a public enum is “fragile” or “closed for evolution”.</div></blockquote><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">So if enums have an attribute that allows API authors to denote the fragility enums, then this can be handled via that route.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">Another potential fix is that&nbsp;<em class="">only</em>&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">internal</code>&nbsp;and&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">private</code>&nbsp;scoped functions are allowed to use the exhaustive-style catch-clauses. For all&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">public</code>&nbsp;APIs, they would still need the catch-all clauses.</p><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">For APIs that return non-enum based&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>&nbsp;implementations, then no, this does not contribute to the fragility problem.</p><h5 style="margin: 20px 0px 10px; padding: 0px; -webkit-font-smoothing: antialiased; cursor: text; position: relative; font-size: 14px; font-family: Helvetica, arial, sans-serif; background-color: rgb(255, 255, 255);" class="">Aren’t we creating the need for wrapper errors?</h5><p style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255);" class="">This is a philosophical debate. I’ll simply state that I believe that simply re-throwing an error, say some type of IO error, from your API that is not an IO-based API is design flaw: you are exposing implementation details to users. This creates a fragile API surface.</p><p style="margin-top: 15px; margin-right: 0px; margin-left: 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255); margin-bottom: 0px !important;" class="">Also, since the type annotation is opt-in, I feel like this is a really minor argument. If your function is really able to throw errors from various different API calls, then just stick with the default&nbsp;<code style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">ErrorType</code>.</p></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAdKtNNCrSfEopzz3Kff89W4OlBmEwy2-2FVSP8g-2BwF16U9-2BqXt6VjkuULzqySxwRzEGbTgNf21pc20Bu56oRAH4ntmeQMDChtuGtNc-2Bu4DDwmRFejvF1hQtjYOOccRJpfwPuoG1MkyhGGScgD4xszbVshfME-2FjR8dthJLfEI-2F-2FSs29hO7EY5-2B3FA-2Foqp5tOHc-2BFY-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>