<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Fri, Feb 17, 2017 at 4:46 PM Joe Groff via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Feb 17, 2017, at 11:03 AM, Adrian Zubarev via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-3197068117490666070Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div class="m_-3197068117490666070bloop_markdown gmail_msg" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(254,254,254)"><p style="margin:15px 0px" class="gmail_msg">I suggest we need to find a way to shorten the list of the possible error types with a the help of<span class="m_-3197068117490666070Apple-converted-space gmail_msg"> </span><code style="font-family:Menlo,Consolas,'Liberation Mono',Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:1px solid rgb(234,234,234);margin:0px 2px;padding:0px 5px;word-break:normal;word-wrap:normal" class="gmail_msg">typeallias</code></p><pre style="margin:15px 0px;font-family:Menlo,Consolas,'Liberation Mono',Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:1px solid rgb(204,204,204);overflow:auto;padding:4px 8px;word-break:normal;word-wrap:normal" class="gmail_msg"><code class="m_-3197068117490666070swift gmail_msg" style="font-family:Menlo,Consolas,'Liberation Mono',Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:0px;margin:0px;padding:0px;word-break:normal;word-wrap:normal">extension MyError1: Error { ... }
extension MyError2: Error { ... }
extension MyError3: Error { ... }
typealias MyErrors = MyError1 | MyError2 | MyError3
func foo() throws(MyErrors) -> MyResult
func bar<T : Error>(_: () throws(T) -> Void) rethrows(MyErrors, T) -> MyResult
</code></pre></div></div></blockquote></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg">Do you actually need that? Experience in other languages like Rust and Haskell that use Result-based error propagation suggests that a single error type is adequate, and beneficial in many ways. If nothing else, you could `Either` your way to multiple errors if you really needed to.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">IMO, if we accept a single error type per function, there could be a simpler model for this. We could say that the `throws` type is a generic parameter of all function types, and it defaults to the uninhabited `Never` type for functions that don't throw.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">() -> () == () throws Never -> ()</div><div class="gmail_msg">() throws -> () == () throws Error -> ()</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In this model, you'd get many benefits:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">- `rethrows` could become first-class, reducing down to just polymorphic `throws`:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">func foo(_: () throws -> ()) rethrows // Swift 3</div><div class="gmail_msg">func foo<T: Error>(_: () throws T -> ()) throws T // Swift X</div>func foo<T: Error>(_: () throws T -> ()) throws Either<MyErrors, T><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">- Protocols could abstract over error handling; for instance, we could support throwing sequences:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">protocol IteratorProtocol {</div><div class="gmail_msg"> associatedtype Element</div><div class="gmail_msg"> associatedtype Error: Swift.Error = Never</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"> mutating func next() throws Error -> Element?</div><div class="gmail_msg">}</div><div class="gmail_msg"><br class="gmail_msg"></div></div></blockquote><div><br></div><div>I really dig this proposal, Joe. Matches my experience from other languages as well.</div><div><br></div><div>-Colin</div><div><br></div></div></div>