<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Dec 30, 2017 at 11:35 PM, Nevin Brackett-Rozinsky via swift-users <span dir="ltr">&lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">So, I know this doesn’t actually address your issue, but I think it is important to clarify that “rethrows” does not guarantee anything about the *type* of error thrown by a function. What “rethrows” implies is that the function *will not throw* unless at least one of its arguments throws.<div><br></div><div>In particular, if the argument throws, the outer function can throw *any error or none at all*. For example,</div><div><br></div><div><div><font face="monospace, monospace">enum CatError: Error { case hairball }</font></div><div><font face="monospace, monospace">enum DogError: Error { case chasedSkunk }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">func foo(_ f: () throws -&gt; Void) rethrows -&gt; Void {</font></div><div><font face="monospace, monospace">    do    { try f() }</font></div><div><font face="monospace, monospace">    catch { throw CatError.hairball }</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">do {</font></div><div><font face="monospace, monospace">    try foo{ throw DogError.chasedSkunk }</font></div><div><font face="monospace, monospace">} catch {</font></div><div><font face="monospace, monospace">    print(error)    // hairball</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>Inside foo’s catch block, it is legal to throw any error, or not throw an error at all. But *outside* that catch block foo cannot throw, which is causing you consternation.</div><div><br></div><div>• • •</div><div><br></div><div>I don’t have a good solution for you, but in attempting to find one I *did* uncover something which compiles that probably shouldn’t. It seems that a “rethrows” function is currently allowed to throw if a *local* function throws:</div><div><br></div><div><div><span style="font-family:monospace,monospace">func rethrowing(_ f: () throws -&gt; Void) rethrows -&gt; Void {</span><br></div><div><font face="monospace, monospace">    func localThrowing() throws -&gt; Void { throw CatError.hairball }</font></div><div><font face="monospace, monospace">    return try localThrowing()</font></div><div><font face="monospace, monospace">}</font></div></div></div></blockquote><div><br></div><div>Yikes, that looks bad; worth filing a bug at <a href="http://bugs.swift.org">bugs.swift.org</a> if there isn&#39;t one already.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">do {</font></div><div><font face="monospace, monospace">    try rethrowing</font><span style="font-family:monospace,monospace">{ throw DogError.chasedSkunk }</span></div><div><font face="monospace, monospace">} catch {</font></div><div><font face="monospace, monospace">    print(error)    // hairball</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>I wouldn’t count on this functionality as it is most likely a bug. Indeed, if we pass in a non-throwing argument then we get a runtime error:</div><div><br></div><div><font face="monospace, monospace">rethrowing{ return }  // EXC_BAD_ACCESS (code=1, address=0x0)</font><br></div><div><br></div><div>Although, if we change “localThrowing” to use do/catch on a call to “f” and throw only in the catch block, or even use your “var caught: Error?” trick, then it appears to work as intended with no problems at runtime.<br></div><div><br></div><div>• • •</div><div><br></div><div>In the unlikely scenario that the above local-function behavior is valid and intended, the following function will, technically speaking, let you work around the issue you’re having:</div><div><br></div><div><span class=""><div><font face="monospace, monospace">func withPredicateErrors &lt;Element, Return&gt;</font></div><div><font face="monospace, monospace">    (_ predicate: (Element) throws -&gt; Bool,</font></div></span><div><font face="monospace, monospace">     do body: @escaping ((Element) -&gt; Bool) -&gt; Return</font></div><div><font face="monospace, monospace">    ) rethrows -&gt; Return</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace">    func bodyWrapper(_ f: (Element) throws -&gt; Bool) throws -&gt; Return {</font></div><span class=""><div><font face="monospace, monospace">        var caught: Error?</font></div><div><font face="monospace, monospace">        let value = body{ elem in</font></div><div><font face="monospace, monospace">            do {</font></div></span><div><font face="monospace, monospace">                return try f(elem)</font></div><span class=""><div><font face="monospace, monospace">            } catch {</font></div><div><font face="monospace, monospace">                caught = error</font></div><div><font face="monospace, monospace">                return true</font></div><div><font face="monospace, monospace">            }</font></div><div><font face="monospace, monospace">        }</font></div></span><span class=""><div><font face="monospace, monospace">        if let caught = caught { throw caught }</font></div></span><div><font face="monospace, monospace">        return value</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    return try bodyWrapper(predicate)</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>It is not pretty, and it probably relies on a compiler bug, but at the present time, against all odds, it look like this operates as you intend.</div><div><br></div><div>Nevin<br></div><div><br></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 30, 2017 at 11:15 PM, Brent Royal-Gordon via swift-users <span dir="ltr">&lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I need to do something like this:<br>
<br>
        func withPredicateErrors&lt;Element, Return&gt;(_ predicate: (Element) throws -&gt; Bool, do body: ((Element) -&gt; Bool) -&gt; Return) rethrows -&gt; Return {<br>
          var caught: Error?<br>
          let value = body { elem in<br>
            do {<br>
              return try predicate(elem)<br>
            }<br>
            catch {<br>
              caught = error<br>
              return true     // Terminate search<br>
            }<br>
          }<br>
<br>
          if let caught = caught {<br>
            throw caught<br>
          }<br>
          else {<br>
            return value<br>
          }<br>
        }<br>
<br>
The problem is, the Swift compiler doesn&#39;t allow the explicit `throw` statement; even though it can only throw errors originally thrown by `predicate`, the compiler is not smart enough to prove that to itself. I cannot make `body` a `throws` function.<br>
<br>
Is there any way to do this? Either to override the compiler&#39;s safety check, or to rewrite this function to avoid it?<br>
<span class="m_5861890967369103144HOEnZb"><font color="#888888"><br>
--<br>
Brent Royal-Gordon<br>
Architechies<br>
<br>
______________________________<wbr>_________________<br>
swift-users mailing list<br>
<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-users</a><br>
</font></span></blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
swift-users mailing list<br>
<a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-users</a><br>
<br></blockquote></div><br></div></div>