<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 Jun 30, 2016, at 1:30 PM, Scott James Remnant via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">+1</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I continually find the use of `as` for bridging between Objective-C and Swift types to be confusing, since they do not have a true place in the Swift type hierarchy and are not simple casts. The `catch let error as NSError` construct always implies that NSError is a true type that can be thrown, and this confusion gets worse in the places where NSError “leaks” out of APIs and you can’t actually cleanly bridge from an ErrorProtocol anyway.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>The weird and convoluted behavior of the “as” keyword is one of the uglier (and more error-prone) warts in the language as it currently stands. There was a proposal a while back to remove the bridging behavior from the “as” keyword, greatly simplifying its behavior, but discussion on it seems to have died down. I hope it can be revived once this proposal is accepted, since the need for “as NSError” was one of the main problems with that proposal.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">One comment though:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Why is the errorDescription of LocalizedError an optional? Why would a type conform to this protocol, and then choose not to provide its only extension to ErrorProtocol?</span></div></blockquote></div><br class=""><div class="">This one’s my fault; Gregory originally had this as a non-optional and I recommended changing it, because Cocoa uses a nil value for NSLocalizedDescriptionKey to indicate that the default behavior should be used to construct the error string. In my experience, this is usually in fact what you want, and NSLocalizedFailureReasonErrorKey is a better fit for most purposes. For example, when throwing an error in an NSDocument subclass:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">override</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">func</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> read(from data: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">Data</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, ofType typeName: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">String</span><span class="" style="font-variant-ligatures: no-common-ligatures;">) </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throws</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> {</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> userInfo = [</span><span class="" style="font-variant-ligatures: no-common-ligatures;">NSLocalizedFailureReasonErrorKey</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throw</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">NSError</span><span class="" style="font-variant-ligatures: no-common-ligatures;">(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo)</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">}</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">In the example above, the error is presented to the user as “The operation could not be completed. Something went wrong.”</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">However, if you fill in the localized description instead of the failure reason, like this:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">override</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">func</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> read(from data: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">Data</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, ofType typeName: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">String</span><span class="" style="font-variant-ligatures: no-common-ligatures;">) </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throws</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> {</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);"> userInfo = [</span><span class="" style="font-variant-ligatures: no-common-ligatures;">NSLocalizedDescriptionKey</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(0, 0, 0);">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throw</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">NSError</span><span class="" style="font-variant-ligatures: no-common-ligatures;">(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo)</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">}</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-variant-ligatures: no-common-ligatures;">The user is shown “The operation could not be completed.” with no further information.</span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">Even when you’re reporting errors directly, the behavior is different whether you provide the localized description or omit it. With a nil description, as below:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [NSLocalizedFailureReasonErrorKey: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">NSApp.presentError(NSError(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo))</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;"><span class="" style="font-family: Helvetica; font-size: 12px;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span class="" style="font-variant-ligatures: no-common-ligatures;"></span>The error is presented as “The operation could not be completed. Something went wrong.” By comparison, if we provide the description:</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;"><span class="" style="font-variant-ligatures: no-common-ligatures;"></span><br class=""></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [NSLocalizedDescriptionKey: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">NSApp.presentError(NSError(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo))</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">The error is simply reported as “Something went wrong.” This seems somewhat brusque, compared to the more polite and blow-softening behavior of the former example.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Unfortunately, I can’t think of any way for this property to return a non-optional, human-readable string to the end user while still communicating to NSError that the field should be nil, unless the default implementation can either copy the code that NSError uses to generate this value, or call through to NSError to generate it. I do notice that NSError always returns something appropriate when you call -localizedDescription on it, although it has the advantage that that method is only used to retrieve the value, not to provide it, unlike here.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Charles</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div></div></div></div></body></html>