# Typed throw functions

**URL:** <https://forums.swift.org/t/typed-throw-functions/38860>\
**Category:** Discussion\
**Tags:** throw, swift, error\
**Created:** [July 29, 2020, 11:34am UTC](https://forums.swift.org/t/typed-throw-functions/38860 "2020-07-29T11:34:11Z")\
**Posts on this page:** 1\
**Showing post:** 33

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [August 3, 2020, 11:22am UTC](https://forums.swift.org/t/typed-throw-functions/38860/33 "2020-08-03T11:22:34Z")

</div>

> [@minuscorp](#):
>
> I don't see any issue with what your statement tells. Is therre any issue with making a switch? Even further, that issue, if it is, it can occur now with the standard error catching but multiplied to infinity enums that conform to Error, so I rather stick with just one.

Sure - so my issue with typed throws isn't so much with the specific feature itself. `Error` is just a marker protocol, and by itself is no more useful than `Any`. You wouldn't write an API taking `Any` parameters and returning `Any` results, so it makes writing code (especially code which actually _handles errors_) more awkward to write as you have to claw back that type information via dynamic casts and handle failure cases which you know will never happen (especially in a single module).

That said, I think that introducing typed throws right now would lead to an overall worse error model than we currently have. There are a couple of reasons for this, mostly revolving around enums. Conceptually, enums are a really great fit for modelling errors, so it isn't surprising that those flaws really get exposed through throwing functions. Also, I agree with @Lantua that the major motivating use-case for typed throws is exhaustive catching, and that only works on enums anyway. So enums and typed throws have a very strong link.

The biggest issue is that you cannot add new cases to `public` enums. This is something of a flaw in the language - and has been a [topic](https://forums.swift.org/t/se-0192-non-exhaustive-enums/7291) of much [discussion](https://forums.swift.org/t/se-0192-non-exhaustive-enums-review-2/11043). Essentially, it means that we shouldn't really be allowing exhaustive `switch` or `catch` on enums from other modules in the general case _anyway_ - you should always have to handle `@unknown default` cases, so the enum has freedom to grow. We currently have a quirk in the language so if the enum's declaring module was compiled with `library-evolution`, it will actually be extensible and cannot be exhaustively switched/caught unless you opt-in to that. The thing is - it's also a massive issue for source stability, not just binary compatibility. Unfortunately, there isn't even a way for enums in regular modules to opt-in to that very important flexibility (that's what the proposal I linked to aims to address).

So why is this a problem? Well, let's take your example:

```swift
public enum AuthenticationError: Error {
    case invalidCredentials
    case unknownReason
}

public func authenticate(with username: String, and password: String) throws AuthenticationError

```

Let's imagine this is part of a library - not even an ABI-stable library, it can even be shipped as source. Now, you've had the foresight to add an `unknownReason` catch-all clause, which is good. Lots of developers won't think of that - especially if they've never run in to the issue themselves or frequent these forums to have heard about it. But it won't save you ;)

So they ship the above code in v1.0 - but soon after, they notice some suspect behaviour, and decide to rate-limit the authentication requests. Now, this company has really poor frontend caches, so they recommend (but don't require) that Apps handle this specific error and enforce the limit on the client side. Even with an `unknownReason` case though, we still don't have any ability to add errors to the function, other than bumping it up to v2.0. This creates yet further headaches with package dependency resolution, as all dependencies must be compatible with the same major version of the library.

So you can see how enums make this feature impossible to use without limiting how your function's implementation can evolve, even if it isn't `@inlinable`. That's why I think it's important to fix enums before we give them even more significance by exposing them in this way.

* * *

So that's an overview of the problem. Will it be an actual issue for developers in the real world? I think it will. Just looking at this thread:

> [@minuscorp](#):
>
> in a language where the strong type system is one of its clutch

> [@Sajjon](#):
>
> non-typed throws is awkward and leads to annoying boilerplate

> [@SDGGiesbrecht](#):
>
> I mostly stopped using `throws` when `Result` was added to the standard library, precisely because it self‐documents what can go wrong, and can be easily switched over to get the master list if the error is an enumeration.

> [@Chris\_Lattner3](#):
>
> I have someone in my team that is making exactly the same argument - they eschew `throws` entirely in favor of `Result` because you can type the error correctly.

It sounds very much like people think that typed throws is something that they "should" do. Of course, it would eliminate some boilerplate, but in many cases, it could inadvertently expose some non-obvious pitfalls in the language's library evolution story (both for ABI and source stability).

In general, I agree most with the sentiments expressed by @John_McCall:

> [@\[Pitch\] Typed throws](https://forums.swift.org/t/pitch-typed-throws/5233/41):
>
> The real use case for typed throws is when you have something like a parser library that really does only fail in a fixed number of semantically distinct ways, and you both (1) actually care about enforcing that in the implementation and making sure that other errors are handled internally and (2) you really do expect clients to exhaustively switch over the error at some point. That's important. **But I continue to think that if adding better support for that use case misleads other programmers into thinking they should use typed throws, we will have made the language worse overall.**

P.S. For @Chris_Lattner3: Are those functions public and are the errors enum types? If so, is this person aware of the evolution constraints?

---

_[View the full topic](https://forums.swift.org/t/typed-throw-functions/38860)._
