<div style="white-space:pre-wrap">I did a quick read and this looks great! Thanks to you two for pulling this together.<br><br>I will attempt a deeper read and comment as needed later today. I am interested in helping with this as possible.<br><br>-Shawn</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 27, 2016 at 2:41 PM Douglas Gregor via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; 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">Hi all,<div><br></div><div>Proposal link: <a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md" target="_blank">https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md</a></div><div><br></div><div>Here is a detailed proposal draft for bridging NSError to ErrorProtocol. Getting this right is surprisingly involved, so the detailed design on this proposal is fairly large. Comments welcome!</div><div><br></div><div><span style="white-space:pre-wrap">        </span>- Doug</div><div><br></div></div><div style="word-wrap:break-word"><div><h1 style="font-size:2.25em;margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255);margin-top:0px!important">NSError Bridging</h1><ul style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li>Proposal: <a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/NNNN-nserror-bridging.md" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SE-NNNN</a></li><li>Author: <a href="https://github.com/DougGregor" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Doug Gregor</a>, <a href="https://github.com/CharlesJS" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Charles Srstka</a></li><li>Status: <span>Awaiting review</span></li><li>Review manager: TBD</li></ul><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#introduction" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Introduction</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Swift&#39;s error handling model interoperates directly with Cocoa&#39;s NSError conventions. For example, an Objective-C method with an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError**</code> parameter, e.g.,</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal">- (nullable <span style="color:rgb(0,134,179)">NSURL</span> *)replaceItemAtURL:(<span style="color:rgb(0,134,179)">NSURL</span> *)url options:(<span style="color:rgb(0,134,179)">NSFileVersionReplacingOptions</span>)options error:(<span style="color:rgb(0,134,179)">NSError</span> **)error;</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">will be imported as a throwing method:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">replaceItem</span>(<span style="color:rgb(121,93,163)">at</span> <span>url</span>: URL, options: ReplacingOptions <span style="color:rgb(167,29,93)">=</span> []) throws <span style="color:rgb(167,29,93)">-&gt;</span> URL</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Swift bridges between <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>-conforming types and <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> so, for example, a Swift <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">enum</code> that conforms to<code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> can be thrown and will be reflected as an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> with a suitable domain and code. Moreover, an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>produced with that domain and code can be caught as the Swift <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">enum</code> type, providing round-tripping so that Swift can deal in <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> values while Objective-C deals in <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> objects.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">However, the interoperability is incomplete in a number of ways, which results in Swift programs having to walk a careful line between the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>-based Swift way and the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>-based way. This proposal attempts to bridge those gaps.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Swift-evolution thread: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016618.html" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Charles Srstka&#39;s pitch for Consistent bridging for NSErrors at the language boundary</a>, which discussed Charles&#39; <a href="https://github.com/apple/swift-evolution/pull/331" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">original proposal</a> that addressed these issues by providing <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> bridging and exposing the domain, code, and user-info dictionary for all errors. This proposal expands upon that work, but without directly exposing the domain, code, and user-info.</p><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#motivation" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Motivation</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">There are a number of weaknesses in Swift&#39;s interoperability with Cocoa&#39;s error model, including:</p><ol style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li><p style="margin-top:16px;margin-bottom:16px">There is no good way to provide important error information when throwing an error from Swift. For example, let&#39;s consider a simple application-defined error in Swift:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">enum</span> HomeworkError <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Int</span>, ErrorProtocol {
  <span style="color:rgb(167,29,93)">case</span> forgotten
  <span style="color:rgb(167,29,93)">case</span> lost
  <span style="color:rgb(167,29,93)">case</span> dogAteIt
}</pre></div><p style="margin-top:16px;margin-bottom:16px">One can throw <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">HomeworkError.dogAteIt</code> and it can be interpreted as an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> by Objective-C with an appropriate error domain (effectively, the mangled name of the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">HomeworkError</code> type) and code (effectively, the case discriminator). However, one cannot provide a localized description, help anchor, recovery attempter, or any other information commonly placed into the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary of an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>. To provide these values, one must specifically construct an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> in Swift, e.g.,</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">throw</span> NSError(code: HomeworkError<span style="color:rgb(167,29,93)">.</span>dogAteIt<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">rawValue</span>,
              domain: HomeworkError<span style="color:rgb(167,29,93)">.</span>_domain,
              userInfo: [ NSLocalizedDescriptionKey <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(24,54,145)"><span>&quot;</span>the dog ate it<span>&quot;</span></span> ])</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">There is no good way to get information typically associated with <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>&#39;s <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> in Swift. For example, the Swift-natural way to catch a specific error in the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">AVError</code> error domain doesn&#39;t give one access to the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary, e.g.,:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> <span style="color:rgb(167,29,93)">let</span> error <span style="color:rgb(167,29,93)">as</span> AVError <span style="color:rgb(167,29,93)">where</span> error <span style="color:rgb(167,29,93)">==</span> <span style="color:rgb(167,29,93)">.</span>diskFull {
  <span style="color:rgb(150,152,150)">// AVError is an enum, so one only gets the equivalent of the code.</span>
  <span style="color:rgb(150,152,150)">// There is no way to access the localized description (for example) or</span>
  <span style="color:rgb(150,152,150)">// any other information typically stored in the ``userInfo`` dictionary.</span>
}</pre></div><p style="margin-top:16px;margin-bottom:16px">The workaround is to catch as an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>, which is quite a bit more ugly:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> <span style="color:rgb(167,29,93)">let</span> error <span style="color:rgb(167,29,93)">as</span> NSError <span style="color:rgb(167,29,93)">where</span> error<span style="color:rgb(167,29,93)">.</span>_domain <span style="color:rgb(167,29,93)">==</span> AVFoundationErrorDomain <span style="color:rgb(167,29,93)">&amp;&amp;</span> error<span style="color:rgb(167,29,93)">.</span>_code <span style="color:rgb(167,29,93)">==</span> AVFoundationErrorDomain<span style="color:rgb(167,29,93)">.</span>diskFull<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">rawValue</span> {
  <span style="color:rgb(150,152,150)">// okay: userInfo is finally accessible, but still weakly typed</span>
}</pre></div><p style="margin-top:16px;margin-bottom:16px">This makes it extremely hard to access common information, such as the localized description. Moreover, the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary is effectively untyped so, for example, one has to know a priori that the value associated with the known <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">AVErrorDeviceKey</code> will be typed as <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">CMTime</code>:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> <span style="color:rgb(167,29,93)">let</span> error <span style="color:rgb(167,29,93)">as</span> NSError <span style="color:rgb(167,29,93)">where</span> error<span style="color:rgb(167,29,93)">.</span>_domain <span style="color:rgb(167,29,93)">=</span> AVFoundationErrorDomain {
  <span style="color:rgb(167,29,93)">if</span> <span style="color:rgb(167,29,93)">let</span> time <span style="color:rgb(167,29,93)">=</span> error<span style="color:rgb(167,29,93)">.</span>userInfo[AVErrorDeviceKey] <span style="color:rgb(167,29,93)">as?</span> CMTime {
    <span style="color:rgb(150,152,150)">// ...</span>
  }
}</pre></div><p style="margin-top:16px;margin-bottom:16px">It would be far better if one could catch an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">AVError</code> directly and query the time in a type-safe manner:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> <span style="color:rgb(167,29,93)">let</span> error <span style="color:rgb(167,29,93)">as</span> AVError {
  <span style="color:rgb(167,29,93)">if</span> <span style="color:rgb(167,29,93)">let</span> time <span style="color:rgb(167,29,93)">=</span> error<span style="color:rgb(167,29,93)">.</span>time {
    <span style="color:rgb(150,152,150)">// ...</span>
  }
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px"><code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> is inconsistently bridged with <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>. Swift interoperates by translating between <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> and <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> when mapping between a throwing Swift method/initializer and an Objective-C method with an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError**</code> parameter. However, an Objective-C method that takes an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError*</code> parameter (e.g., to render it) does not bridge to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>, meaning that <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> is part of the API in Swift in some places (but not others). For example, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> leaks through when the following <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">UIDocument</code> API in Objective-C:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal">- (<span style="color:rgb(167,29,93)">void</span>)handleError:(<span style="color:rgb(0,134,179)">NSError</span> *)error userInteractionPermitted:(<span style="color:rgb(167,29,93)">BOOL</span>)userInteractionPermitted;</pre></div><p style="margin-top:16px;margin-bottom:16px">is imported into Swift as follows:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">handleError</span>(<span style="color:rgb(121,93,163)">_</span> <span>error</span>: NSError, userInteractionPermitted: <span style="color:rgb(0,134,179)">Bool</span>)</pre></div><p style="margin-top:16px;margin-bottom:16px">One would expect the first parameter to be imported as <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>. </p></li></ol><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#proposed-solution" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Proposed solution</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal involves directly addressing (1)-(3) with new protocols and a different way of bridging Objective-C error code types into Swift, along with some conveniences for working with Cocoa errors:</p><ol style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><li><p style="margin-top:16px;margin-bottom:16px">Introduce three new protocols for describing more information about errors: <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">LocalizedError</code>, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">RecoverableError</code>, and<code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">CustomNSError</code>. For example, an error type can provide a localized description by conforming to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">LocalizedError</code>:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> HomeworkError <span style="color:rgb(167,29,93)">:</span> LocalizedError {
  <span style="color:rgb(167,29,93)">var</span> errorDescription: <span style="color:rgb(0,134,179)">String</span>? {
    <span style="color:rgb(167,29,93)">switch</span> <span style="color:rgb(167,29,93)">self</span> {
    <span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>forgotten: <span style="color:rgb(167,29,93)">return</span> NSLocalizedString(<span style="color:rgb(24,54,145)"><span>&quot;</span>I forgot it<span>&quot;</span></span>)
    <span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>lost: <span style="color:rgb(167,29,93)">return</span> NSLocalizedString(<span style="color:rgb(24,54,145)"><span>&quot;</span>I lost it<span>&quot;</span></span>)
    <span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>dogAteIt: <span style="color:rgb(167,29,93)">return</span> NSLocalizedString(<span style="color:rgb(24,54,145)"><span>&quot;</span>The dog ate it<span>&quot;</span></span>)
    }
  }
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">Imported Objective-C error types should be mapped to struct types that store an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> so that no information is lost when bridging from an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> to the Swift error types. We propose to introduce a new macro, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NS_ERROR_ENUM</code>, that one can use to both declare an enumeration type used to describe the error codes as well as tying that type to a specific domain constant, e.g.,</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">typedef</span> <span style="color:rgb(121,93,163)">NS_ERROR_ENUM</span>(<span style="color:rgb(167,29,93)">NSInteger</span>, AVError, AVFoundationErrorDomain) {
  AVErrorUnknown                                      = -<span style="color:rgb(0,134,179)">11800</span>,
  AVErrorOutOfMemory                                  = -<span style="color:rgb(0,134,179)">11801</span>,
  AVErrorSessionNotRunning                            = -<span style="color:rgb(0,134,179)">11803</span>,
  AVErrorDeviceAlreadyUsedByAnotherSession            = -<span style="color:rgb(0,134,179)">11804</span>,
  <span style="color:rgb(150,152,150)">// ...</span>
}</pre></div><p style="margin-top:16px;margin-bottom:16px">The imported <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">AVError</code> will have a struct that allows one to access the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary directly. This retains the ability to catch via a specific code, e.g.,</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> AVError<span style="color:rgb(167,29,93)">.</span>outOfMemory {
 <span style="color:rgb(150,152,150)">// ...</span>
}</pre></div><p style="margin-top:16px;margin-bottom:16px">However, catching a specific error as a value doesn&#39;t lose information:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">catch</span> <span style="color:rgb(167,29,93)">let</span> error <span style="color:rgb(167,29,93)">as</span> AVError <span style="color:rgb(167,29,93)">where</span> error<span style="color:rgb(167,29,93)">.</span>code <span style="color:rgb(167,29,93)">==</span> <span style="color:rgb(167,29,93)">.</span>sessionNotRunning {
 <span style="color:rgb(150,152,150)">// able to access userInfo here!</span>
}</pre></div><p style="margin-top:16px;margin-bottom:16px">This also gives the ability for one to add typed accessors for known keys within the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> AVError {
 <span style="color:rgb(167,29,93)">var</span> time: CMTime? {
   <span style="color:rgb(167,29,93)">get</span> {
     <span style="color:rgb(167,29,93)">return</span> userInfo[AVErrorTimeKey] <span style="color:rgb(167,29,93)">as?</span> CMTime?
   }

   <span style="color:rgb(167,29,93)">set</span> {
     userInfo[AVErrorTimeKey] <span style="color:rgb(167,29,93)">=</span> newValue<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">map</span> { $<span style="color:rgb(0,134,179)">0</span> <span style="color:rgb(167,29,93)">as</span> CMTime }
   }
 }
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">Bridge <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code>, so that all <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> uses are bridged consistently. For example, this means that the Objective-C API:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal">- (<span style="color:rgb(167,29,93)">void</span>)handleError:(<span style="color:rgb(0,134,179)">NSError</span> *)error userInteractionPermitted:(<span style="color:rgb(167,29,93)">BOOL</span>)userInteractionPermitted;</pre></div><p style="margin-top:16px;margin-bottom:16px">is imported into Swift as:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">handleError</span>(<span style="color:rgb(121,93,163)">_</span> <span>error</span>: ErrorProtocol, userInteractionPermitted: <span style="color:rgb(0,134,179)">Bool</span>)</pre></div><p style="margin-top:16px;margin-bottom:16px">This will use the same bridging logic in the Clang importer that we use for other value types (<code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Array</code>, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">String</code>, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">URL</code>, etc.), but with the runtime translation we&#39;ve already been doing for catching/throwing errors.</p><p style="margin-top:16px;margin-bottom:16px">When we introduce this bridging, we will need to remove <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>&#39;s conformance to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> to avoid creating cyclic implicit conversions. However, we still need an easy way to create an <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> instance from an arbitrary <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>, e.g.,</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> NSError {
  <span style="color:rgb(167,29,93)">var</span> asError: ErrorProtocol { <span style="color:rgb(167,29,93)">...</span> }
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">In Foundation, add an extension to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> that provides typed access to the common user-info keys. Note that we focus only on those user-info keys that are read by user code (vs. only accessed by frameworks):</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> ErrorProtocol {
  <span style="color:rgb(150,152,150)">// Note: for exposition only. Not actual API.</span>
  <span style="color:rgb(167,29,93)">private</span> <span style="color:rgb(167,29,93)">var</span> userInfo: [NSObject <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">AnyObject</span>] {
    <span style="color:rgb(167,29,93)">return</span> (<span style="color:rgb(167,29,93)">self</span> <span style="color:rgb(167,29,93)">as!</span> NSError)<span style="color:rgb(167,29,93)">.</span>userInfo
  }

  <span style="color:rgb(167,29,93)">var</span> localizedDescription: <span style="color:rgb(0,134,179)">String</span> {
    <span style="color:rgb(167,29,93)">return</span> (<span style="color:rgb(167,29,93)">self</span> <span style="color:rgb(167,29,93)">as!</span> NSError)<span style="color:rgb(167,29,93)">.</span>localizedDescription
  }

  <span style="color:rgb(167,29,93)">var</span> filePath: <span style="color:rgb(0,134,179)">String</span>? {
    <span style="color:rgb(167,29,93)">return</span> userInfo[NSFilePathErrorKey] <span style="color:rgb(167,29,93)">as?</span> <span style="color:rgb(0,134,179)">String</span>
  }

  <span style="color:rgb(167,29,93)">var</span> stringEncoding: <span style="color:rgb(0,134,179)">String</span><span style="color:rgb(167,29,93)">.</span>Encoding? {
    <span style="color:rgb(167,29,93)">return</span> (userInfo[NSStringEncodingErrorKey] <span style="color:rgb(167,29,93)">as?</span> NSNumber)
             <span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">map</span> { <span style="color:rgb(0,134,179)">String</span><span style="color:rgb(167,29,93)">.</span>Encoding(rawValue: $<span style="color:rgb(0,134,179)">0</span><span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">uintValue</span>) }
  }

  <span style="color:rgb(167,29,93)">var</span> underlying: ErrorProtocol? {
    <span style="color:rgb(167,29,93)">return</span> (userInfo[NSUnderlyingErrorKey] <span style="color:rgb(167,29,93)">as?</span> NSError)?<span style="color:rgb(167,29,93)">.</span>asError
  }

  <span style="color:rgb(167,29,93)">var</span> url: URL? {
    <span style="color:rgb(167,29,93)">return</span> userInfo[NSURLErrorKey] <span style="color:rgb(167,29,93)">as?</span> URL
  }
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">Rename <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Error</code>: once we&#39;ve completed the bridging story, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Error</code> becomes the primary way to work with error types in Swift, and the value type to which <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> is bridged:</p><div style="margin-bottom:16px"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">handleError</span>(<span style="color:rgb(121,93,163)">_</span> <span>error</span>: Error, userInteractionPermitted: <span style="color:rgb(0,134,179)">Bool</span>)</pre></div></li></ol><h2 style="margin-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#detailed-design" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Detailed design</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This section details both the design (including the various new protocols, mapping from Objective-C error code enumeration types into Swift types, etc.) and the efficient implementation of this design to interoperate with <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>. Throughout the detailed design, we already assume the name change from <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ErrorProtocol</code> to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Error</code>.</p><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#new-protocols" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><u></u><u></u><u></u><u></u></a>New protocols</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">This proposal introduces several new protocols that allow error types to expose more information about error types.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">LocalizedError</code> protocol describes an error that provides localized messages for display to the end user, all of which provide default implementations. The conforming type can provide implementations for any subset of these requirements:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">protocol</span> LocalizedError <span style="color:rgb(167,29,93)">:</span> Error {
  <span style="color:rgb(150,152,150)">/// A localized message describing what error occurred.</span>
  <span style="color:rgb(167,29,93)">var</span> errorDescription: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">get</span> }

  <span style="color:rgb(150,152,150)">/// A localized message describing the reason for the failure.</span>
  <span style="color:rgb(167,29,93)">var</span> failureReason: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">get</span> }

  <span style="color:rgb(150,152,150)">/// A localized message describing how one might recover from the failure.</span>
  <span style="color:rgb(167,29,93)">var</span> recoverySuggestion: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">get</span> }

  <span style="color:rgb(150,152,150)">/// A localized message providing &quot;help&quot; text if the user requests help.</span>
  <span style="color:rgb(167,29,93)">var</span> helpAnchor: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">get</span> }
}

<span style="color:rgb(167,29,93)">extension</span> LocalizedError {
  <span style="color:rgb(167,29,93)">var</span> errorDescription: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(0,134,179)">nil</span> }
  <span style="color:rgb(167,29,93)">var</span> failureReason: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(0,134,179)">nil</span> }
  <span style="color:rgb(167,29,93)">var</span> recoverySuggestion: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(0,134,179)">nil</span> }
  <span style="color:rgb(167,29,93)">var</span> helpAnchor: <span style="color:rgb(0,134,179)">String</span>? { <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(0,134,179)">nil</span> }
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">RecoverableError</code> protocol describes an error that might be recoverable: </p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">protocol</span> RecoverableError <span style="color:rgb(167,29,93)">:</span> Error {
  <span style="color:rgb(150,152,150)">/// Provides a set of possible recovery options to present to the user.</span>
  <span style="color:rgb(167,29,93)">var</span> recoveryOptions: [<span style="color:rgb(0,134,179)">String</span>] { <span style="color:rgb(167,29,93)">get</span> }

  <span style="color:rgb(150,152,150)">/// Attempt to recover from this error when the user selected the</span>
  <span style="color:rgb(150,152,150)">/// option at the given index. This routine must call resultHandler and</span>
  <span style="color:rgb(150,152,150)">/// indicate whether recovery was successful (or not).</span>
  <span style="color:rgb(150,152,150)">///</span>
  <span style="color:rgb(150,152,150)">/// This entry point is used for recovery of errors handled at a</span>
  <span style="color:rgb(150,152,150)">/// &quot;document&quot; granularity, that do not affect the entire</span>
  <span style="color:rgb(150,152,150)">/// application.</span>
  <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">attemptRecovery</span>(<span style="color:rgb(121,93,163)">optionIndex</span> <span>recoveryOptionIndex</span>: <span style="color:rgb(0,134,179)">Int</span>,
                       <span style="color:rgb(121,93,163)">andThen</span> <span>resultHandler</span>: (recovered: <span style="color:rgb(0,134,179)">Bool</span>) <span style="color:rgb(167,29,93)">-&gt;</span> <span style="color:rgb(0,134,179)">Void</span>)

  <span style="color:rgb(150,152,150)">/// Attempt to recover from this error when the user selected the</span>
  <span style="color:rgb(150,152,150)">/// option at the given index. Returns true to indicate</span>
  <span style="color:rgb(150,152,150)">/// successful recovery, and false otherwise.</span>
  <span style="color:rgb(150,152,150)">///</span>
  <span style="color:rgb(150,152,150)">/// This entry point is used for recovery of errors handled at</span>
  <span style="color:rgb(150,152,150)">/// the &quot;application&quot; granularity, where nothing else in the</span>
  <span style="color:rgb(150,152,150)">/// application can proceed until the attmpted error recovery</span>
  <span style="color:rgb(150,152,150)">/// completes.</span>
  <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">attemptRecovery</span>(<span style="color:rgb(121,93,163)">optionIndex</span> <span>recoveryOptionIndex</span>: <span style="color:rgb(0,134,179)">Int</span>) <span style="color:rgb(167,29,93)">-&gt;</span> <span style="color:rgb(0,134,179)">Bool</span>
}

<span style="color:rgb(167,29,93)">extension</span> RecoverableError {
  <span style="color:rgb(150,152,150)">/// By default, implements document-modal recovery via application-model</span>
  <span style="color:rgb(150,152,150)">/// recovery.</span>
  <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">attemptRecovery</span>(<span style="color:rgb(121,93,163)">optionIndex</span> <span>recoveryOptionIndex</span>: <span style="color:rgb(0,134,179)">Int</span>,
                       <span style="color:rgb(121,93,163)">andThen</span> <span>resultHandler</span>: (<span style="color:rgb(0,134,179)">Bool</span>) <span style="color:rgb(167,29,93)">-&gt;</span> <span style="color:rgb(0,134,179)">Void</span>) {
    resultHandler(recovered: attemptRecovery(optionIndex: recoveryOptionIndex))
  }
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Error types that conform to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">RecoverableError</code> may be given an opportunity to recover from the error. The user can be presented with some number of (localized) recovery options, described by <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">recoveryOptions</code>, and the selected option will be passed to the appropriate <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">attemptRecovery</code> method.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">CustomNSError</code> protocol describes an error that wants to provide custom <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> information. This can be used, e.g., to provide a specific domain/code or to populate <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>&#39;s <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary with values for custom keys that can be accessed from Objective-C code but are not covered by the other protocols.</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(150,152,150)">/// Describes an error type that fills in the userInfo directly.</span>
<span style="color:rgb(167,29,93)">protocol</span> CustomNSError <span style="color:rgb(167,29,93)">:</span> Error {
  <span style="color:rgb(167,29,93)">var</span> errorDomain: <span style="color:rgb(0,134,179)">String</span> { <span style="color:rgb(167,29,93)">get</span> }
  <span style="color:rgb(167,29,93)">var</span> errorCode: <span style="color:rgb(0,134,179)">Int</span> { <span style="color:rgb(167,29,93)">get</span> }
  <span style="color:rgb(167,29,93)">var</span> errorUserInfo: [<span style="color:rgb(0,134,179)">String</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">AnyObject</span>] { <span style="color:rgb(167,29,93)">get</span> }
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Note that, unlike with <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>, the provided <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">errorUserInfo</code> requires <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">String</code> keys. This is in line with common practice for <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code> and is important for the implementation (see below). All of these properties are defaulted, so one can provide any subset:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> CustomNSError {
  <span style="color:rgb(167,29,93)">var</span> errorDomain: <span style="color:rgb(0,134,179)">String</span> { <span style="color:rgb(167,29,93)">...</span> }
  <span style="color:rgb(167,29,93)">var</span> errorCode: <span style="color:rgb(0,134,179)">Int</span> { <span style="color:rgb(167,29,93)">...</span> }
  <span style="color:rgb(167,29,93)">var</span> errorUserInfo: [<span style="color:rgb(0,134,179)">String</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">AnyObject</span>] { <span style="color:rgb(167,29,93)">...</span> }
}</pre></div><h3 style="margin-top:1em;margin-bottom:16px;line-height:1.43;font-size:1.5em;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;background-color:rgb(255,255,255)"><a href="https://github.com/DougGregor/swift-evolution/blob/nserror-bridging/proposals/0000-nserror-bridging.md#mapping-error-types-to-nserror" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><u></u><u></u><u></u><u></u></a>Mapping error types to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:inherit;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code></h3></div></div><div style="word-wrap:break-word"><div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Every type that conforms to the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Error</code> protocol is implicitly bridged to <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSError</code>. This has been the case since Swift 2, where the compiler provides a domain (i.e., the mangled name of the type) and code (based on the discriminator of the enumeration type). This proposal also allows for the <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary to be populated by the runtime, which will check for conformance to the various protocols (<code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">LocalizedError</code>, <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">RecoverableError</code>, or <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">CustomNSError</code>) to retrieve information.</p></div></div><div style="word-wrap:break-word"><div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)">Conceptually, this could be implemented by eagerly creating a <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">userInfo</code> dictionary for a given instance of <code style="font-family:Consolas,&#39;Liberation Mono&#39;,Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Error</code>:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:&#39;Helvetica Neue&#39;,Helvetica,&#39;Segoe UI&#39;,Arial,freesans,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;;font-size:16px;background-color:rgb(255,255,255)"></div></div></div></blockquote></div>