Seeing in the Apple doc that the Task
is defined as:
@frozen struct Task<Success, Failure> where Success : Sendable, Failure : Error
I've seen a number of code online where people add extensions to Task
with constraint like:
extension Task where Failure == Error {}
and/or
extension Task where Success == Sendable {}
For example, the code here extends Task
with the constraint Failure == Error
. Given that Task
is defined with constraint Failure: Error
I wonder what's the specific need for adding Failure == Error
?
Thanks!
A type satisfies the : Error
constraint if it conforms to Error
. For example, this type:
enum MyError: Error {
case somethingBadHappened
}
However, MyError
does not satisfy an == Error
constraint, because the only type that satisfies this constraint is Error
itself. It says "equal to" Error
, after all :)
You can apply the same logic to Sendable
.
The versions of Task.init
and Task.detached
that take a throwing closure, and relayResult
in your linked code, all requires == Error
, because they all create tasks from a throwing closure.
You don't know what specific type of Error
a throwing closure is going to throw. The best you know is it throws Error
. Therefore, these methods can only create a task whose failure type is exactly Error
. They cannot create a task whose failure type is, say, MyError
,
// let's say that calling Task.init with Failure being MyError is allowed
Task<SomeSuccessType, MyError> {
// some code that throws AnotherError
}
because the throwing closure can throw AnotherError
.
But let's say the "throwing other types of errors" problem is magically handled somehow, this == Error
also serves as an easy way for the compiler to infer the Failure
type when you call these methods. You don't need to write the type of error the task can throw explicitly, like I did above.
I can't think of when you would use exactly Sendable
as the Success
type off the top of my head though. That doesn't seem very useful.
Sendable
doesn't have any syntactic requirements, so it is functionally the same as using exactly Void
(aka ()
, and also conforms to Sendable
) as the Success
type, to indicate "this task just "finishes" and has no result". If I were to choose, I would definitely choose Void
instead of Sendable
to express this idea.