Typed throws

To summarize: as of today we have two different cases of rethrows.

1:

func foo(_ bar: () throws -> ()) rethrows {
    try bar()
}

2:

func foo(_ bar: () throws -> ()) rethrows {
    do {
        try bar()
    } catch {
        throw CustomError(base: error)
    }
}

Both of these should continue to work exactly as they are now, without any source code changes required.

Maybe I'm overseeing something, but I will just write my idea nonetheless.


If we had a typed throws, we would need a typed rethrows as well.

Our two cases, that we have today would work exactly the same, as they worked in the past. I repeat them here with the implicit types in comments.

1:

func foo(_ bar: () throws /* Error */ -> ()) rethrows /* Error */ {
    try bar()
}

2:

func foo(_ bar: () throws /* Error */ -> ()) rethrows /* Error */ {
    do {
        try bar()
    } catch {
        throw CustomError(base: error)
    }
}

AFAIUI, this is the pre-typed-throws-behaviour.

Now we want the same but with typed Errors as well. So we have the following additional cases:

3 (typed version of (1)):

func foo<E>(_ bar: () throws E -> ()) rethrows E {
    try bar()
}

// If every function implicitly threw Never, we could write
func foo<E>(_ bar: () throws E -> ()) throws E {
    try bar()
}
// which would semantically be the same

4 (typed version of (2)):

func foo<E>(_ bar: () throws E -> ()) rethrows CustomError {
    do {
        try bar()
    } catch {
        throw CustomError(base: error)
    }
}

I cannot think of a reason ATM, why this should not work.

6 Likes