Sure, though this is used when the original error isn't an appropriate description of the problem at the current API level (e.g.
FileManager will wrap a
POSIXError with a
CocoaError because the fact that Cocoa's file management routines are implemented by POSIX APIs is an implementation detail and not something that
FileManager's clients should have to deal with). When my API involves decoding JSON into a model object, and and I get a decoding error, that decoding error is the appropriate thing to pass to my clients already, and wrapping it serves no purpose.
No I'm concerned that the actual error will be ignored. The error with semantic meaning got wrapped by one without, so unless you go digging into the underlying error, you actually lose meaning with this wrapping. I don't want to design an API that forces all of my users to dig into the underlying error in order to actually get the information they need, and I don't want the "obvious action" (taking the error and logging it to analytics) to produce a bad result.
Logging the original JSON in the same string as the actual error text is very explicitly a bad thing. That makes it really hard to coalesce error logs together or extract any meaningful information in aggregate. I want to log the actual error, which can then be handled appropriately in aggregate, and I want to attach the source text as secondary information that I can use if I dig into the individual logged errors as part of diagnosing the issue.
More generally, literally the only reason to have the
Failure type conform to
Error is because the Swift core team doesn't want to encourage people to use
String as their error type. That's it. There's no technical benefit, as we can trivially make
get() into a conditional extension. And I would argue that forcing the
Failure type to conform to
Error actually serves no purpose and is a holdover from thinking of this as a replacement for
throws is specifically an error mechanism, and everything it throws should be an error. We already have a separate mechanism for returning one of two different value types (namely, a 2-variant enum with associated values), and the purpose of
throws is very explicitly to implement an error strategy, including propagating errors up the stack, along with explicit
catch blocks to catch them, etc.
Result is not specifically an error mechansim. It's the representation of the outcome of a failable computation. The failure state for a computation may not necessarily be an error. It will probably include an error, though even that isn't a requirement. More generally,
Result does not directly tie into the rest of the error-handling mechanism. There is no automatic propagation of
Results up the stack, no
catch block construct that deals with it, and no automatic coalescing of multiple error types into a single existential (e.g. there's no built-in way to combine a
Result<Int,FooError> with a
Result<Int,BarError>). The fact that the
Failure type is constrained on
Error has no benefit and only makes
Result more awkward to use outside of the limited scenario of "I'm taking a
throws API and representing it with
Also, there's precedent in Cocoa for wanting to have
Failure not specifically conform to
Error. What I'm thinking about is
URLSession.dataTask(with:completion:). This API cannot be converted to use
Result without retaining the ugly optional
URLResponse? type in the handler, even though we know for a fact that the success case includes a
URLResponse and we'd really like to make it non-optional. The ideal completion handler type here is
(Result<(URLResponse, Data), (URLResponse?, Error)>) -> Void, but this is not a type that can be written as long as
Failure is constrained to