<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=""><div><blockquote type="cite" class=""><div class="">On Feb 20, 2017, at 3:46 PM, Karl Wagner <<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>> wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">On 20 Feb 2017, at 18:57, John McCall <<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; 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; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Feb 19, 2017, at 3:04 PM, Anton Zhilin via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><div dir="ltr" class=""><div class="markdown-here-wrapper"><p class="" style="margin: 0px 0px 1.2em !important;">It’s expected that if you need resilience, then you will throw an “open” enum. Essentially, we pass resilience of typed<span class="Apple-converted-space"> </span><code class="" style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; 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; display: inline;">throws</code><span class="Apple-converted-space"> </span>on to those who will hopefully establish resilience of enums.</p><p class="" style="margin: 0px 0px 1.2em !important;">If you prefer separate error types, then declare a base protocol for all your error types and throw a protocol existential. You won’t even need default case in switches, if closed protocols make it into the language.</p><p class="" style="margin: 0px 0px 1.2em !important;">I don’t like any solution that is based on comments. I think that compiler should always ignore comments.</p></div></div></div></blockquote><div class="">I agree. And in general, this sort of thing is exactly my core concern about adding typed throws to the language: I am completely certain that many programmers will add typed throws annotations because they're programmers and thus, well, probably a little obsessive/compulsive, and they're trying to precisely document the behavior of their function without necessarily thinking about the usefulness of that information for their clients and (if they're writing a library; and really you should almost always be writing code as if you're writing a library) whether they're actually willing to commit to that behavior in their interface. For those programmers, typed throws is just going to box them in and force them into anti-patterns in the long run.</div><div class=""><br class=""></div><div class="">In the vast majority of use-cases, clients are not going to exhaustively handle all errors — they will always have some generic fall-back. That is not pessimism, it's actually the natural result of the complicated world we live in, where code can fail for a huge host of reasons and most callers won't have meaningful special-case behavior for all of them. (On most operating systems, opening a file or a network connection can fail because you ran out of file descriptors. You're seriously telling me that you're going to add a special case to your error logic for that?) Go look at the actual error types that people use in most typed-throws situations and try to tell me I'm wrong — they probably have like twenty alternatives, and solidly a quarter or more of them will just be embedding some other arbitrarily-complex or stringly-typed error value.</div><div class=""><br class=""></div><div class="">The real use case for typed throws is when you have something like a parser library that really does only fail in a fixed number of semantically distinct ways, and you both (1) actually care about enforcing that in the implementation and making sure that other errors are handled internally and (2) you really do expect clients to exhaustively switch over the error at some point. That's important. But I continue to think that if adding better support for that use case misleads other programmers into thinking they should use typed throws, we will have made the language worse overall.</div><div class=""><br class=""></div><div class="">John.</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="markdown-here-wrapper"><p class="" style="margin: 0px 0px 1.2em !important;">2017-02-18 18:27 GMT+03:00 Karl Wagner <<a href="mailto:razielim@gmail.com" target="_blank" class="">razielim@gmail.com</a>>:</p><div class="" style="margin: 0px 0px 1.2em !important;"><br class="webkit-block-placeholder"></div><div class="markdown-here-exclude"><div class=""><br class="webkit-block-placeholder"></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div class="" style="word-wrap: break-word;"><div class=""><br class=""></div><div class="">So, I’m not sure about what was decided last time, but my issues with this are:</div><div class=""><br class=""></div><div class="">- The thrown error type will become part of the ABI of the function. If you change the type of Error that is thrown, callers may not catch it. At the same time, if we make enums resilient by default and only allow specifying a single entire type, you will basically need one Error enum per function and it will need to be @fixed if you actually want to remove the catch-all block. Otherwise:</div><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">// Let’s say this isn’t @fixed...</font></div></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">enum CanFailError {</font></div><div class=""><font face="Courier" class=""> errorOne</font></div><div class=""><font face="Courier" class=""> errorTwo</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">func canFail() throws(CanFailError) { /* … */ }</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">do { try canFail() }</font></div><div class=""><font face="Courier" class="">catch </font><span class="" style="font-family: Courier;">CanFailError</span><font face="Courier" class=""> {</font></div><div class=""><font face="Courier" class=""> switch error {</font></div><div class=""><font face="Courier" class=""> case .errorOne: /* handle error one */</font></div><div class=""><font face="Courier" class=""> case .errorTwo: /* handle error two */</font></div><div class=""><font face="Courier" class=""> default: /* handle possible new errors in later versions of the library */</font></div><div class=""><font face="Courier" class=""> }</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><div class=""><font face="Courier" class="">do { try canFail() }</font></div><div class=""><font face="Courier" class="">catch .errorOne { /* handle error one */ }</font></div><div class=""><font face="Courier" class="">catch .errorTwo { /* handle error two */ }</font></div><div class=""><font face="Courier" class="">catch { /* handle possible new errors in later versions of the library */ }</font></div><div class=""><br class=""></div></div></blockquote>- I usually have _semantic_ namespaces for Errors, rather than single types per implementation pattern. If we are adding strong annotations about which errors can be thrown, I’d quite like to incorporate that pattern. For example:<div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">extension File {</font></div></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">@fixed </font><span class="" style="font-family: Courier;">enum OpeningError { </span></div></blockquote></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><span class="m_3187643400478788723Apple-tab-span" style="font-family: Courier; white-space: pre-wrap;">        </span><span class="" style="font-family: Courier;">case .invalidPath</span><br class=""><span class="m_3187643400478788723Apple-tab-span" style="font-family: Courier; white-space: pre-wrap;">        </span><span class="" style="font-family: Courier;">case .accessDenied // e.g. asking for write permissions for read-only file</span><br class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class="">@fixed enum ReadError {</font></div></blockquote><span class="m_3187643400478788723Apple-tab-span" style="font-family: Courier; white-space: pre-wrap;">        </span><span class="" style="font-family: Courier;">case .invalidOffset // past EOF</span><br class=""><span class="m_3187643400478788723Apple-tab-span" style="font-family: Courier; white-space: pre-wrap;">        </span><span class="" style="font-family: Courier;">case .deviceError // probably worth aborting the entire operation the read is part of</span><br class=""><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">// - throws:</font></div><div class=""><font face="Courier" class="">// - .OpeningError if the file can’t be opened</font></div><div class=""><font face="Courier" class="">// - .ReadError if the read operation fails</font></div><div class=""><font face="Courier" class="">func read(from offset: Int, into buffer: UnsafeBufferPointer<UInt8>) throws(OpeningError, ReadError) { /* … */ }</font></div></blockquote><font face="Courier" class="">}</font></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><br class=""></blockquote>- I wonder if we could try something more ambitious. Since the list of thrown errors is resilience-breaking for the function, it is only beneficial for versioned and @inlineable functions. They should not be able to add new errors (they can remove them though, since errors are intended to be switched over). I wonder if we couldn’t introduce a small pattern grammar for our structured comments (isolated from the rest of the language) - it would be optional, but if you do list your errors, the compiler would validate that you do it exhaustively. Some patterns I would like are:<div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Courier" class="">// - throws: - MyError.{errorOne, errorThree, errorFive}: Something bad || considered exhaustive</font></div><div class=""><font face="Courier" class="">@inlineable public func canFail() throws {}</font></div><div class=""><br class=""></div><div class=""><font face="Courier" class="">// - throws: - OpeningError: Computer says nooooo... || considered exhaustive if OpeningError is versioned or @fixed</font></div><div class=""><div class=""><font face="Courier" class="">// - * || other errors, requires “catch-all” by external callers</font></div></div><div class=""><div class=""><font face="Courier" class="">@inlineable public func canFail2() throws {}</font></div></div><div class=""><font face="Courier" class=""><br class=""></font></div></blockquote><div class=""><div class="">If we want to get really clever, we can have the compiler automatically generate those error-lists for internal functions, so you would automatically get exhaustive error-handling within your own module.<span class="HOEnZb"><font color="#888888" class=""><br class=""><div class=""><br class=""></div></font></span></div></div><span class="HOEnZb"><font color="#888888" class=""><div class="">- Karl</div></font></span></div></blockquote><div class=""><br class="webkit-block-placeholder"></div></div><div class="" style="margin: 0px 0px 1.2em !important;"><br class="webkit-block-placeholder"></div><div title="MDH:SXQncyBleHBlY3RlZCB0aGF0IGlmIHlvdSBuZWVkIHJlc2lsaWVuY2UsIHRoZW4geW91IHdpbGwg
dGhyb3cgYW4gIm9wZW4iIGVudW0uIEVzc2VudGlhbGx5LCB3ZSBwYXNzIHJlc2lsaWVuY2Ugb2Yg
dHlwZWQgYHRocm93c2Agb24gdG8gdGhvc2Ugd2hvIHdpbGwgaG9wZWZ1bGx5IGVzdGFibGlzaCBy
ZXNpbGllbmNlIG9mIGVudW1zLjxkaXY+PGJyPjwvZGl2PjxkaXY+SWYgeW91IHByZWZlciBzZXBh
cmF0ZSBlcnJvciB0eXBlcywgdGhlbiBkZWNsYXJlIGEgYmFzZSBwcm90b2NvbCBmb3IgYWxsIHlv
dXIgZXJyb3IgdHlwZXMgYW5kIHRocm93IGEgcHJvdG9jb2wgZXhpc3RlbnRpYWwuIFlvdSB3b24n
dCBldmVuIG5lZWQgZGVmYXVsdCBjYXNlIGluIHN3aXRjaGVzLCBpZiBjbG9zZWQgcHJvdG9jb2xz
IG1ha2UgaXQgaW50byB0aGUgbGFuZ3VhZ2UuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5JIGRv
bid0IGxpa2UgYW55IHNvbHV0aW9uIHRoYXQgaXMgYmFzZWQgb24gY29tbWVudHMuIEkgdGhpbmsg
dGhhdCBjb21waWxlciBzaG91bGQgYWx3YXlzIGlnbm9yZSBjb21tZW50cy48YnI+PGRpdiBjbGFz
cz0iZ21haWxfZXh0cmEiPjxicj48ZGl2IGNsYXNzPSJnbWFpbF9xdW90ZSI+MjAxNy0wMi0xOCAx
ODoyNyBHTVQrMDM6MDAgS2FybCBXYWduZXIgPHNwYW4gZGlyPSJsdHIiPiZsdDs8YSBocmVmPSJt
YWlsdG86cmF6aWVsaW1AZ21haWwuY29tIiB0YXJnZXQ9Il9ibGFuayI+cmF6aWVsaW1AZ21haWwu
Y29tPC9hPiZndDs8L3NwYW4+OjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9
Im1hcmdpbjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVm
dDoxZXgiPjxkaXYgc3R5bGU9IndvcmQtd3JhcDpicmVhay13b3JkIj48ZGl2Pjxicj48L2Rpdj48
ZGl2PlNvLCBJ4oCZbSBub3Qgc3VyZSBhYm91dCB3aGF0IHdhcyBkZWNpZGVkIGxhc3QgdGltZSwg
YnV0IG15IGlzc3VlcyB3aXRoIHRoaXMgYXJlOjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+LSBU
aGUgdGhyb3duIGVycm9yIHR5cGUgd2lsbCBiZWNvbWUgcGFydCBvZiB0aGUgQUJJIG9mIHRoZSBm
dW5jdGlvbi4gSWYgeW91IGNoYW5nZSB0aGUgdHlwZSBvZiBFcnJvciB0aGF0IGlzIHRocm93biwg
Y2FsbGVycyBtYXkgbm90IGNhdGNoIGl0LiBBdCB0aGUgc2FtZSB0aW1lLCBpZiB3ZSBtYWtlIGVu
dW1zIHJlc2lsaWVudCBieSBkZWZhdWx0IGFuZCBvbmx5IGFsbG93IHNwZWNpZnlpbmcgYSBzaW5n
bGUgZW50aXJlIHR5cGUsIHlvdSB3aWxsIGJhc2ljYWxseSBuZWVkIG9uZSBFcnJvciBlbnVtIHBl
ciBmdW5jdGlvbiBhbmQgaXQgd2lsbCBuZWVkIHRvIGJlIEBmaXhlZCBpZiB5b3UgYWN0dWFsbHkg
d2FudCB0byByZW1vdmUgdGhlIGNhdGNoLWFsbCBibG9jay4gT3RoZXJ3aXNlOjwvZGl2PjxkaXY+
PGJyPjwvZGl2PjxibG9ja3F1b3RlIHN0eWxlPSJtYXJnaW46MCAwIDAgNDBweDtib3JkZXI6bm9u
ZTtwYWRkaW5nOjBweCI+PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVyIj4vLyBMZXTigJlzIHNheSB0
aGlzIGlzbuKAmXQgQGZpeGVkLi4uPC9mb250PjwvZGl2PjwvYmxvY2txdW90ZT48YmxvY2txdW90
ZSBzdHlsZT0ibWFyZ2luOjAgMCAwIDQwcHg7Ym9yZGVyOm5vbmU7cGFkZGluZzowcHgiPjxkaXY+
PGZvbnQgZmFjZT0iQ291cmllciI+ZW51bSBDYW5GYWlsRXJyb3IgezwvZm9udD48L2Rpdj48ZGl2
Pjxmb250IGZhY2U9IkNvdXJpZXIiPiZuYnNwOyAmbmJzcDsgZXJyb3JPbmU8L2ZvbnQ+PC9kaXY+
PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVyIj4mbmJzcDsgJm5ic3A7IGVycm9yVHdvPC9mb250Pjwv
ZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+fTwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZh
Y2U9IkNvdXJpZXIiPjxicj48L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVyIj5m
dW5jIGNhbkZhaWwoKSB0aHJvd3MoQ2FuRmFpbEVycm9yKSB7IC8qIOKApiAqLyB9PC9mb250Pjwv
ZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+PGJyPjwvZm9udD48L2Rpdj48ZGl2Pjxmb250
IGZhY2U9IkNvdXJpZXIiPmRvIHsgdHJ5IGNhbkZhaWwoKSB9PC9mb250PjwvZGl2PjxkaXY+PGZv
bnQgZmFjZT0iQ291cmllciI+Y2F0Y2gmbmJzcDs8L2ZvbnQ+PHNwYW4gc3R5bGU9ImZvbnQtZmFt
aWx5OkNvdXJpZXIiPkNhbkZhaWxFcnJvcjwvc3Bhbj48Zm9udCBmYWNlPSJDb3VyaWVyIj4mbmJz
cDt7PC9mb250PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+Jm5ic3A7ICZuYnNwOyBz
d2l0Y2ggZXJyb3IgezwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPiZuYnNw
OyAmbmJzcDsgJm5ic3A7ICZuYnNwOyBjYXNlIC5lcnJvck9uZTogLyogaGFuZGxlIGVycm9yIG9u
ZSAqLzwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPiZuYnNwOyAmbmJzcDsg
Jm5ic3A7ICZuYnNwOyBjYXNlIC5lcnJvclR3bzogLyogaGFuZGxlIGVycm9yIHR3byAqLzwvZm9u
dD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPiZuYnNwOyAmbmJzcDsgJm5ic3A7ICZu
YnNwOyBkZWZhdWx0OiAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsvKiBoYW5kbGUgcG9zc2li
bGUgbmV3IGVycm9ycyBpbiBsYXRlciB2ZXJzaW9ucyBvZiB0aGUgbGlicmFyeSAqLzwvZm9udD48
L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPiZuYnNwOyAmbmJzcDsgfTwvZm9udD48L2Rp
dj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPn08L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNl
PSJDb3VyaWVyIj48YnI+PC9mb250PjwvZGl2PjxkaXY+PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVy
Ij5kbyB7IHRyeSBjYW5GYWlsKCkgfTwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJp
ZXIiPmNhdGNoIC5lcnJvck9uZSB7IC8qIGhhbmRsZSBlcnJvciBvbmUgKi8gfTwvZm9udD48L2Rp
dj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPmNhdGNoIC5lcnJvclR3byB7IC8qIGhhbmRsZSBl
cnJvciB0d28gKi8gJm5ic3A7fTwvZm9udD48L2Rpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIi
PmNhdGNoICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgeyAvKiBoYW5kbGUgcG9z
c2libGUgbmV3IGVycm9ycyBpbiBsYXRlciB2ZXJzaW9ucyBvZiB0aGUgbGlicmFyeSAqLyB9PC9m
b250PjwvZGl2PjxkaXY+PGJyPjwvZGl2PjwvZGl2PjwvYmxvY2txdW90ZT4tIEkgdXN1YWxseSBo
YXZlIF9zZW1hbnRpY18gbmFtZXNwYWNlcyBmb3IgRXJyb3JzLCByYXRoZXIgdGhhbiBzaW5nbGUg
dHlwZXMgcGVyIGltcGxlbWVudGF0aW9uIHBhdHRlcm4uIElmIHdlIGFyZSBhZGRpbmcgc3Ryb25n
IGFubm90YXRpb25zIGFib3V0IHdoaWNoIGVycm9ycyBjYW4gYmUgdGhyb3duLCBJ4oCZZCBxdWl0
ZSBsaWtlIHRvIGluY29ycG9yYXRlIHRoYXQgcGF0dGVybi4gRm9yIGV4YW1wbGU6PGRpdj48YnI+
PC9kaXY+PGJsb2NrcXVvdGUgc3R5bGU9Im1hcmdpbjowIDAgMCA0MHB4O2JvcmRlcjpub25lO3Bh
ZGRpbmc6MHB4Ij48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPmV4dGVuc2lvbiBGaWxlIHs8L2Zv
bnQ+PC9kaXY+PC9ibG9ja3F1b3RlPjxibG9ja3F1b3RlIHN0eWxlPSJtYXJnaW46MCAwIDAgNDBw
eDtib3JkZXI6bm9uZTtwYWRkaW5nOjBweCI+PGJsb2NrcXVvdGUgc3R5bGU9Im1hcmdpbjowIDAg
MCA0MHB4O2JvcmRlcjpub25lO3BhZGRpbmc6MHB4Ij48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIi
PkBmaXhlZCZuYnNwOzwvZm9udD48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmllciI+ZW51
bSBPcGVuaW5nRXJyb3IgeyZuYnNwOzwvc3Bhbj48L2Rpdj48L2Jsb2NrcXVvdGU+PC9ibG9ja3F1
b3RlPjxibG9ja3F1b3RlIHN0eWxlPSJtYXJnaW46MCAwIDAgNDBweDtib3JkZXI6bm9uZTtwYWRk
aW5nOjBweCI+PHNwYW4gY2xhc3M9Im1fMzE4NzY0MzQwMDQ3ODc4ODcyM0FwcGxlLXRhYi1zcGFu
IiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmllcjt3aGl0ZS1zcGFjZTpwcmUtd3JhcCI+CTwvc3Bh
bj48c3BhbiBzdHlsZT0iZm9udC1mYW1pbHk6Q291cmllciI+Y2FzZSAuaW52YWxpZFBhdGg8L3Nw
YW4+PGJyPjxzcGFuIGNsYXNzPSJtXzMxODc2NDM0MDA0Nzg3ODg3MjNBcHBsZS10YWItc3BhbiIg
c3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJpZXI7d2hpdGUtc3BhY2U6cHJlLXdyYXAiPgk8L3NwYW4+
PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkNvdXJpZXIiPmNhc2UgLmFjY2Vzc0RlbmllZCAmbmJz
cDsvLyBlLmcuIGFza2luZyBmb3Igd3JpdGUgcGVybWlzc2lvbnMgZm9yIHJlYWQtb25seSBmaWxl
PC9zcGFuPjxicj48YmxvY2txdW90ZSBzdHlsZT0ibWFyZ2luOjAgMCAwIDQwcHg7Ym9yZGVyOm5v
bmU7cGFkZGluZzowcHgiPjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+fTwvZm9udD48L2Rpdj48
ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPkBmaXhlZCBlbnVtIFJlYWRFcnJvciB7PC9mb250Pjwv
ZGl2PjwvYmxvY2txdW90ZT48c3BhbiBjbGFzcz0ibV8zMTg3NjQzNDAwNDc4Nzg4NzIzQXBwbGUt
dGFiLXNwYW4iIHN0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyO3doaXRlLXNwYWNlOnByZS13cmFw
Ij4JPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyIj5jYXNlIC5pbnZhbGlk
T2Zmc2V0IC8vIHBhc3QgRU9GPC9zcGFuPjxicj48c3BhbiBjbGFzcz0ibV8zMTg3NjQzNDAwNDc4
Nzg4NzIzQXBwbGUtdGFiLXNwYW4iIHN0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyO3doaXRlLXNw
YWNlOnByZS13cmFwIj4JPC9zcGFuPjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyIj5j
YXNlIC5kZXZpY2VFcnJvciAmbmJzcDsgLy8gcHJvYmFibHkgd29ydGggYWJvcnRpbmcgdGhlIGVu
dGlyZSBvcGVyYXRpb24gdGhlIHJlYWQgaXMgcGFydCBvZjwvc3Bhbj48YnI+PGJsb2NrcXVvdGUg
c3R5bGU9Im1hcmdpbjowIDAgMCA0MHB4O2JvcmRlcjpub25lO3BhZGRpbmc6MHB4Ij48ZGl2Pjxm
b250IGZhY2U9IkNvdXJpZXIiPn08L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVy
Ij48YnI+PC9mb250PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+Ly8gLSB0aHJvd3M6
PC9mb250PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+Ly8gJm5ic3A7ICZuYnNwOyAt
IC5PcGVuaW5nRXJyb3IgaWYgdGhlIGZpbGUgY2Fu4oCZdCBiZSBvcGVuZWQ8L2ZvbnQ+PC9kaXY+
PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVyIj4vLyAmbmJzcDsgJm5ic3A7IC0gLlJlYWRFcnJvciBp
ZiB0aGUgcmVhZCBvcGVyYXRpb24gZmFpbHM8L2ZvbnQ+PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJD
b3VyaWVyIj5mdW5jIHJlYWQoZnJvbSBvZmZzZXQ6IEludCwgaW50byBidWZmZXI6IFVuc2FmZUJ1
ZmZlclBvaW50ZXImbHQ7VUludDgmZ3Q7KSB0aHJvd3MoT3BlbmluZ0Vycm9yLCBSZWFkRXJyb3Ip
IHsgLyog4oCmICovIH08L2ZvbnQ+PC9kaXY+PC9ibG9ja3F1b3RlPjxmb250IGZhY2U9IkNvdXJp
ZXIiPn08L2ZvbnQ+PC9ibG9ja3F1b3RlPjxibG9ja3F1b3RlIHN0eWxlPSJtYXJnaW46MCAwIDAg
NDBweDtib3JkZXI6bm9uZTtwYWRkaW5nOjBweCI+PGJyPjwvYmxvY2txdW90ZT4tIEkgd29uZGVy
IGlmIHdlIGNvdWxkIHRyeSBzb21ldGhpbmcgbW9yZSBhbWJpdGlvdXMuIFNpbmNlIHRoZSBsaXN0
IG9mIHRocm93biBlcnJvcnMgaXMgcmVzaWxpZW5jZS1icmVha2luZyBmb3IgdGhlIGZ1bmN0aW9u
LCBpdCBpcyBvbmx5IGJlbmVmaWNpYWwgZm9yIHZlcnNpb25lZCBhbmQgQGlubGluZWFibGUgZnVu
Y3Rpb25zLiBUaGV5IHNob3VsZCBub3QgYmUgYWJsZSB0byBhZGQgbmV3IGVycm9ycyAodGhleSBj
YW4gcmVtb3ZlIHRoZW0gdGhvdWdoLCBzaW5jZSBlcnJvcnMgYXJlIGludGVuZGVkIHRvIGJlIHN3
aXRjaGVkIG92ZXIpLiBJIHdvbmRlciBpZiB3ZSBjb3VsZG7igJl0IGludHJvZHVjZSBhIHNtYWxs
IHBhdHRlcm4gZ3JhbW1hciBmb3Igb3VyIHN0cnVjdHVyZWQgY29tbWVudHMgKGlzb2xhdGVkIGZy
b20gdGhlIHJlc3Qgb2YgdGhlIGxhbmd1YWdlKSAtIGl0IHdvdWxkIGJlIG9wdGlvbmFsLCBidXQg
aWYgeW91IGRvIGxpc3QgeW91ciBlcnJvcnMsIHRoZSBjb21waWxlciB3b3VsZCB2YWxpZGF0ZSB0
aGF0IHlvdSBkbyBpdCBleGhhdXN0aXZlbHkuIFNvbWUgcGF0dGVybnMgSSB3b3VsZCBsaWtlIGFy
ZTo8ZGl2Pjxicj48L2Rpdj48YmxvY2txdW90ZSBzdHlsZT0ibWFyZ2luOjAgMCAwIDQwcHg7Ym9y
ZGVyOm5vbmU7cGFkZGluZzowcHgiPjxkaXY+PGZvbnQgZmFjZT0iQ291cmllciI+Ly8gLSB0aHJv
d3M6IC0gTXlFcnJvci57ZXJyb3JPbmUsIGVycm9yVGhyZWUsIGVycm9yRml2ZX06IFNvbWV0aGlu
ZyBiYWQgJm5ic3A7ICZuYnNwOyAmbmJzcDt8fCBjb25zaWRlcmVkIGV4aGF1c3RpdmU8L2ZvbnQ+
PC9kaXY+PGRpdj48Zm9udCBmYWNlPSJDb3VyaWVyIj5AaW5saW5lYWJsZSBwdWJsaWMgZnVuYyBj
YW5GYWlsKCkgdGhyb3dzIHt9PC9mb250PjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGZvbnQg
ZmFjZT0iQ291cmllciI+Ly8gLSB0aHJvd3M6IC0mbmJzcDtPcGVuaW5nRXJyb3I6IENvbXB1dGVy
IHNheXMgbm9vb29vLi4uICZuYnNwOyAmbmJzcDsgfHwgY29uc2lkZXJlZCBleGhhdXN0aXZlIGlm
IE9wZW5pbmdFcnJvciBpcyB2ZXJzaW9uZWQgb3IgQGZpeGVkPC9mb250PjwvZGl2PjxkaXY+PGRp
dj48Zm9udCBmYWNlPSJDb3VyaWVyIj4vLyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5i
c3A7IC0gKiAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsg
Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAm
bmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IHx8IG90aGVyIGVycm9ycywgcmVxdWly
ZXMg4oCcY2F0Y2gtYWxs4oCdIGJ5IGV4dGVybmFsIGNhbGxlcnM8L2ZvbnQ+PC9kaXY+PC9kaXY+
PGRpdj48ZGl2Pjxmb250IGZhY2U9IkNvdXJpZXIiPkBpbmxpbmVhYmxlIHB1YmxpYyBmdW5jIGNh
bkZhaWwyKCkgdGhyb3dzIHt9PC9mb250PjwvZGl2PjwvZGl2PjxkaXY+PGZvbnQgZmFjZT0iQ291
cmllciI+PGJyPjwvZm9udD48L2Rpdj48L2Jsb2NrcXVvdGU+PGRpdj48ZGl2PklmIHdlIHdhbnQg
dG8gZ2V0IHJlYWxseSBjbGV2ZXIsIHdlIGNhbiBoYXZlIHRoZSBjb21waWxlciBhdXRvbWF0aWNh
bGx5IGdlbmVyYXRlIHRob3NlIGVycm9yLWxpc3RzIGZvciBpbnRlcm5hbCBmdW5jdGlvbnMsIHNv
IHlvdSB3b3VsZCBhdXRvbWF0aWNhbGx5IGdldCBleGhhdXN0aXZlIGVycm9yLWhhbmRsaW5nIHdp
dGhpbiB5b3VyIG93biBtb2R1bGUuPHNwYW4gY2xhc3M9IkhPRW5aYiI+PGZvbnQgY29sb3I9IiM4
ODg4ODgiPjxicj48ZGl2Pjxicj48L2Rpdj48L2ZvbnQ+PC9zcGFuPjwvZGl2PjwvZGl2PjxzcGFu
IGNsYXNzPSJIT0VuWmIiPjxmb250IGNvbG9yPSIjODg4ODg4Ij48ZGl2Pi0gS2FybDwvZGl2Pjwv
Zm9udD48L3NwYW4+PC9kaXY+PC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48L2Rpdj48L2Rpdj4=" class="" style="height: 0px; width: 0px; max-height: 0px; max-width: 0px; overflow: hidden; font-size: 0em; padding: 0px; margin: 0px;"></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div></div></blockquote></div><br class=""><div class=""><br class=""></div><div class="">I agree, and that’s where I was going with it: I think that typed-throws should basically be something on the level of a stronger comment rather than something so definitive as the function’s ABI. That’s how it will be much of the time in practice, anyway.</div><div class=""><br class=""></div><div class="">I don’t believe having a single error type is really ideal for anything. We’ve basically whittled down the feature until it gets in the way. If every function is throwing its own enum or hidden under complex hierarchies of protocols, it becomes difficult to write helper routines which respond to common errors in certain ways (e.g. trying an operation if if failed because the network was down).</div><div class=""><br class=""></div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class="">// Using one-enum per function<br class=""><br class=""></font></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class="">enum FunctionOneError: Error {<br class=""> case networkWasDown(shouldTryAgain: Bool)<br class=""> case otherReason<br class="">}<br class="">func functionOne() throws(FunctionOneError)<br class=""><br class=""></font></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class="">enum FunctionTwoError: Error {<br class=""> case networkWasDown(shouldTryAgain: Bool)<br class=""> case aDifferentReason<br class="">}<br class="">func functionTwo() throws(FunctionTwoError)</font></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class=""><br class="">// How to use this information at a high level?</font></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class=""><br class="">func retryIfNetworkDown(let attempts: Int = 3, work: ()throws->Void) rethrows -> Bool { // <- Can’t specify which errors we take, or which we rethrow<br class=""> for n in 0..<attempts {<br class=""> do { try work() }<br class=""> catch FunctionOneError.networkWasDown(let tryAgain) {<br class=""> if tryAgain, n<attempts { continue }<br class=""> else { return false }<br class=""> }<br class=""> catch FunctionTwoError.networkWasDown(let tryAgain) { // Needs to handle per-function errors :(<br class=""> if tryAgain, n<attempts { continue }<br class=""> else { return false }<br class=""> }</font></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><font face="Courier" class=""> catch { throw error }<br class=""> }</font><div class=""><font face="Courier" class="">}</font></div></blockquote><div class=""><font face="Courier" class=""><br class=""></font></div><div class="">So I’ve heard people say you should create a protocol then, but that’s not really a convenient solution either...</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">protocol NetworkError {</font></div><div class=""><font face="Courier" class=""> func wasNetworkDownAndShouldTryAgain() -> (Bool, Bool)</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">extension FunctionOneError: NetworkError {</font></div><div class=""><font face="Courier" class=""> func wasNetworkDownAndShouldTryAgain() -> (Bool, Bool) {</font></div><div class=""><font face="Courier" class=""> guard case .networkWasDown(let tryAgain) = self else { return (false, false) }</font></div><div class=""><font face="Courier" class=""> return (true, tryAgain)</font></div><div class=""><font face="Courier" class=""> }</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">// This needs to be done twice, too...</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><div class=""><font face="Courier" class="">extension FunctionTwoError: NetworkError {</font></div></div><div class=""><div class=""><font face="Courier" class=""> func wasNetworkDownAndShouldTryAgain() -> (Bool, Bool) {</font></div></div><div class=""><div class=""><font face="Courier" class=""> guard case .networkWasDown(let tryAgain) = self else { return (false, false) }</font></div></div><div class=""><div class=""><font face="Courier" class=""> return (true, tryAgain)</font></div></div><div class=""><div class=""><font face="Courier" class=""> }</font></div></div><div class=""><div class=""><font face="Courier" class="">}</font></div></div></blockquote><div class=""><br class=""></div><div class=""><br class=""></div><div class="">So I think it all descends in to lots of syntax for very marginal amounts of value. Typed-throws is never likely to be the wondrous 100% cross-library reliability guarantee that people dream of. I view it more like good documentation.</div></div></div></blockquote><br class=""></div><div>I completely agree that what most programmers are looking for is just a blessed way to document that a function is likely to throw specific kinds of error, and that certain of them might be worth considering in the caller.</div><div><br class=""></div><div>John.</div><br class=""></body></html>