On Sat, Dec 30, 2017 at 11:35 PM, Nevin Brackett-Rozinsky via swift-users < swift-users@swift.org> wrote:
> 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. > > In particular, if the argument throws, the outer function can throw *any > error or none at all*. For example, > > enum CatError: Error { case hairball } > enum DogError: Error { case chasedSkunk } > > func foo(_ f: () throws -> Void) rethrows -> Void { > do { try f() } > catch { throw CatError.hairball } > } > > do { > try foo{ throw DogError.chasedSkunk } > } catch { > print(error) // hairball > } > > 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. > > • • • > > 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: > > func rethrowing(_ f: () throws -> Void) rethrows -> Void { > func localThrowing() throws -> Void { throw CatError.hairball } > return try localThrowing() > } > Yikes, that looks bad; worth filing a bug at bugs.swift.org if there isn't one already. > > do { > try rethrowing{ throw DogError.chasedSkunk } > } catch { > print(error) // hairball > } > > 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: > > rethrowing{ return } // EXC_BAD_ACCESS (code=1, address=0x0) > > 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. > > • • • > > 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: > > func withPredicateErrors <Element, Return> > (_ predicate: (Element) throws -> Bool, > do body: @escaping ((Element) -> Bool) -> Return > ) rethrows -> Return > { > func bodyWrapper(_ f: (Element) throws -> Bool) throws -> Return { > var caught: Error? > let value = body{ elem in > do { > return try f(elem) > } catch { > caught = error > return true > } > } > if let caught = caught { throw caught } > return value > } > > return try bodyWrapper(predicate) > } > > 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. > > Nevin > > > > On Sat, Dec 30, 2017 at 11:15 PM, Brent Royal-Gordon via swift-users < > swift-users@swift.org> wrote: > >> I need to do something like this: >> >> func withPredicateErrors<Element, Return>(_ predicate: (Element) >> throws -> Bool, do body: ((Element) -> Bool) -> Return) rethrows -> Return { >> var caught: Error? >> let value = body { elem in >> do { >> return try predicate(elem) >> } >> catch { >> caught = error >> return true // Terminate search >> } >> } >> >> if let caught = caught { >> throw caught >> } >> else { >> return value >> } >> } >> >> The problem is, the Swift compiler doesn'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. >> >> Is there any way to do this? Either to override the compiler's safety >> check, or to rewrite this function to avoid it? >> >> -- >> Brent Royal-Gordon >> Architechies >> >> _______________________________________________ >> swift-users mailing list >> swift-users@swift.org >> https://lists.swift.org/mailman/listinfo/swift-users >> > > > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users > >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users