# \[Pitch N+1\] Typed Throws

**URL:** <https://forums.swift.org/t/pitch-n-1-typed-throws/67496>\
**Category:** Pitches\
**Created:** [September 25, 2023, 4:25am UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496 "2023-09-25T04:25:05Z")\
**Posts on this page:** 20\
**Page:** 5

<div class="post-metadata">

**Author:** ![Samasaur](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/samasaur/32/8344_2.png) [@Samasaur](https://forums.swift.org/u/Samasaur)\
**Post date:** [September 27, 2023, 6:26pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/82 "2023-09-27T18:26:41Z")

</div>

Strong +1 for this feature. It'll be very nice to use internally inside modules, and I could even see some use cases for public APIs

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [September 27, 2023, 6:30pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/83 "2023-09-27T18:30:39Z")

</div>

Overall the updated version looks really great!

> init(catching body: () throws -\> Success) where Failure == any Error { ... }  
> Replace this with an initializer that uses typed throws:  
> init(catching body: () throws(Failure) -\> Success)

If we add such an initializer isn't this a potential source breaking change since the new type of the `Result` is going to have a typed throw and it might be stored in a `Result<Foo, any Error>`. This store might not happen on the same line but further down in the program and just rely on the currently inferred type. Same applies to the `Task` and `[Checked|Unsafe]Continuation` APIs.

> The `with(Checked|Unsafe)ThrowingContinuation` operations should incorporate typed throws, e.g.,:

This feels a bit weird because one can suddenly create a non-throwing continuation from the `with(Checked|Unsafe)ThrowingContinuation` APIs. Personally I would prefer extending the `with(Checked|Unsafe)Continuation` and drop all of the _throwing_ in API naming. This looks like it is possible since by just introducing a new method with a generic parameter. Relatedly, we might be able to mark the _throwing_ variants as deprecated.

**Task groups**  
Similar to the continuation APIs the proposal should mention what happens with task groups. They also benefit from gaining a typed throw which is the error thrown from the body closure. Additionally, it might make sense to introduce an API where one can restrict the error thrown from the child tasks similar to how one can specify the `childTaskResultType` and `group.next()` & `group.waitForAll()` would now also be constrained to error type.  
I haven't fully explored what implications typed throws have on all the task group APIs but we should revisit all of them. One thing to check here is if `group.next()` or `group.waitForAll()` are currently throwing a `CancellationError` or not.

**Async[Throwing]Stream**  
Similar story here, we should discuss what implications typed throws has on `AsyncStream` and if we could adopt typed throws on it. Probably only `AsyncThrowingStream` can adopt typed throws here. @Douglas_Gregor is it possible to make the `next()` method from `AsyncThrowingStream` throw the generic `Failure` parameter without breaking ABI?

---

<div class="post-metadata">

**Author:** ![sliemeobn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sliemeobn/32/27698_2.png) [@sliemeobn](https://forums.swift.org/u/sliemeobn)\
**Post date:** [September 27, 2023, 6:46pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/84 "2023-09-27T18:46:47Z")

</div>

> [@FranzBusch](#):
>
> This feels a bit weird because one can suddenly create a non-throwing continuation from the `with(Checked|Unsafe)ThrowingContinuation` APIs. Personally I would prefer extending the `with(Checked|Unsafe)Continuation` and drop all of the _throwing_ in API naming. This looks like it is possible since by just introducing a new method with a generic parameter. Relatedly, we might be able to mark the _throwing_ variants as deprecated.

Getting rid of all the noise around throwing vs non-throwing types and _withNnn_ companions would be a huge step! If I think about concurrency-land (continuations, AsyncSequence implementations, TaskGroups, ...) - being able to deprecate out all _throwing_ versions and have it all automagically work with typed throws would be oh so very wonderful!

man, my excitement is at 110% percent - please make this a reality, it's too good not to have it now ; )

---

<div class="post-metadata">

**Author:** ![let\_zeppelin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/let_zeppelin/32/31541_2.png) [@let\_zeppelin](https://forums.swift.org/u/let_zeppelin)\
**Post date:** [September 27, 2023, 7:10pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/85 "2023-09-27T19:10:57Z")

</div>

> [@toph42](#):
>
> ```swift
> do {
> try callCat() // throws CatError
> try callKids() // throw KidError
> } catch {
> // implicit 'error' variable has type 'any Error'
> }
> 
> ```

Regarding this example: Wouldn't this close the door for potential future directions where we would like to have exhaustive catching of all potential error types?

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 7:18pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/86 "2023-09-27T19:18:51Z")

</div>

> [@let\_zeppelin](#):
>
> > [@toph42](#):
> >
> > ```swift
> > do {
> > try callCat() // throws CatError
> > try callKids() // throw KidError
> > } catch {
> > // implicit 'error' variable has type 'any Error'
> > }
> > 
> > ```
> 
> Regarding this example: Wouldn't this close the door for potential future directions where we would like to have exhaustive catching of all potential error types?

I don't think so - it could always be refined further in future, such as if sum types are added to the language, such that the implicit `error` variable is e.g. `CatError | KidError` (or whatever the symbolic notation might end up being). I think that would be source-compatible since `any Error` is a superset of any possible sum type (in this context), so anything you were already doing in the catch clause would still work…?

---

<div class="post-metadata">

**Author:** ![dwaite](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dwaite/32/1200_2.png) [@dwaite](https://forums.swift.org/u/dwaite)\
**Post date:** [September 27, 2023, 7:20pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/87 "2023-09-27T19:20:05Z")

</div>

> [@Douglas\_Gregor](#):
>
> Yes, that's a good point: the proposal should describe the it's appropriate to use typed throws. Here's where I think one should use typed throws:
> 
> 1. In dependency-free code that will only ever produce it errors itself.
> 2. In code that stays within a module/package where you always want to handle the error, so it's a purely an implementation detail.
> 3. In generic code that never produces its own errors, but only passes through errors that come from user components. The standard library is like this.
> 
> Any time a public API will (or may in the future) thrown an error produced by one of its dependencies, it should use untyped throws. In general, most APIs are expected to use untyped throws.

Conceptually, I've thought of a typed throws as being useful when you want the ergonomics and language features today given by untyped throws in code which otherwise might just return `Result<T,E>`

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 7:25pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/88 "2023-09-27T19:25:40Z")

</div>

> [@Douglas\_Gregor](#):
>
> > [@wadetregaskis](#):
> >
> > So a good example of why stronger typing for errors is necessary.
> 
> I don't think it is. I think it's a cautionary tale about the perils of trying to specifically pick out certain thrown error types/values for special handling. If this API were using typed throws, then it could have introduced a new `DecodingError.numberIsNotRepresentable` case to throw, and the problem would be the same.

Perhaps I wasn't clear. I wasn't saying typed throws as pitched here would unequivocally have solved this (although, maybe - perhaps this API would have been using `throws(DecodingError)` which would have precluded an ABI-compatible-but-functionally-incompatible change of throwing a `JSONError`).

I only said it's an example where _stronger typing for errors_ would have helped.

In this case, to be completely safe it would have had to enumerate the _specific_ error values that could be thrown, thus the problem would be clearly revealed both on the library side (function no longer throws one of its declared errors) and on the caller side (function adds a new error case, which is either ABI-breaking and would have been handled some other way (e.g. a new version of the function) or would have already been required to be handled by callers through a `default` catch clause (which, in this specific example, may or may not have avoided the issue entirely depending on the details, but which at least makes it more resilient generally)).

i.e. it's the age-old enum problem, just in an error context. All the normal safe-guards that Swift has around enums _could_ be applied here to errors and would have made it much harder for a breaking change like this in an OS update.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [September 27, 2023, 7:27pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/89 "2023-09-27T19:27:05Z")

</div>

I am torn on this feature.

On one hand it makes language more precise.  
On another hand it makes language more complicated and in many cases this feature will not be used.

Will this feature be more useful because of the cases when it is needed than a nuisance when it is not needed?

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [September 27, 2023, 7:36pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/90 "2023-09-27T19:36:25Z")

</div>

> [@FranzBusch](#):
>
> Overall the updated version looks really great!
> 
> > init(catching body: () throws -\> Success) where Failure == any Error { ... }  
> > Replace this with an initializer that uses typed throws:  
> > init(catching body: () throws(Failure) -\> Success)
> 
> If we add such an initializer isn't this a potential source breaking change since the new type of the `Result` is going to have a typed throw and it might be stored in a `Result<Foo, any Error>`. This store might not happen on the same line but further down in the program and just rely on the currently inferred type. Same applies to the `Task` and `[Checked|Unsafe]Continuation` APIs.

The initializer itself isn't a source-breaking change, because for every existing function is either throwing or not---it doesn't have typed throws. Once you start adopting typed throws in an API, that typed-throw information will ripple through these APIs. And that's a good thing: it means we don't break any existing code, but once you start adopting typed throws you get

To be fair, the change to make `Task.sleep` and `Task.checkCancellation` use typed throws are source-breaking. Maybe we should reconsider those changes, or pull them out into a separate document.

There are specific callouts for "Swift 6" in the proposal that show places where we have to hold back on inferring typed throws to maintain source compatibility.

> [@FranzBusch](#):
>
> This feels a bit weird because one can suddenly create a non-throwing continuation from the `with(Checked|Unsafe)ThrowingContinuation` APIs. Personally I would prefer extending the `with(Checked|Unsafe)Continuation` and drop all of the _throwing_ in API naming. This looks like it is possible since by just introducing a new method with a generic parameter. Relatedly, we might be able to mark the _throwing_ variants as deprecated.

It might be... I should probably pull the concurrency API updates into a separate proposal, because there are going to be a lot of them.

> [@FranzBusch](#):
>
> @Douglas_Gregor is it possible to make the `next()` method from `AsyncThrowingStream` throw the generic `Failure` parameter without breaking ABI?

Yes, although it might involve a little trickery.

> [@tera](#):
>
> Will this feature be more useful because of the cases when it is needed than a nuisance when it is not needed?

I think it will be mostly invisible, and only become a nuisance if someone decides to use it where it shouldn't be used, and gets themself stuck.

Doug

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 7:39pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/91 "2023-09-27T19:39:29Z")

</div>

> [@Douglas\_Gregor](#):
>
> I think it's a cautionary tale about the perils of trying to specifically pick out certain thrown error types/values for special handling

Also, just thinking about this point more, if you take that attitude then why have error types at all? Why not just have `throw` with no argument, and only `} catch {` with no qualifiers? Or at best some completely opaque type that's only `CustomDebugStringConvertible` or somesuch so you can log it but do nothing much else?

I'm a bit confused, now, about what your interest in typed throws is (as a co-author of the proposal!) if you don't actually want the thrown values used…?

(I'm not trying to be rude or a smart-arse or anything, I'm just genuinely a bit thrown by your comment.)

Or am I just jumping to the wrong conclusion when you say "the perils…", as in, do you mean not that it should never be done but that you have to be judicious and/or extra defensive or somesuch?

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [September 27, 2023, 7:47pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/92 "2023-09-27T19:47:05Z")

</div>

> [@wadetregaskis](#):
>
> Also, just thinking about this point more, if you take that attitude then why have error types at all? Why not just have `throw` with no argument, and only `} catch {` with no qualifiers? Or at best some completely opaque type that's only `CustomDebugStringConvertible` or somesuch so you can log it but do nothing much else?
> 
> I'm a bit confused, now, about what your interest in typed throws is (as a co-author of the proposal!) if you don't actually want the thrown values used…?

I didn't say "don't do it", I said one has to be careful, and I was most specifically not wanting folks to conclude that typed throws would have saved this headache and should therefore be used everywhere.

There's a case to be made that the library itself should have stuck with the same error type and added a new case instance, because the language has affordances for dealing with new cases in existing libraries. That's independent of typed throws, and my [criteria for when to use typed throws](https://github.com/minuscorp/swift-typed-throws/blob/master/SE-XXX%20Typed%20throws.md#when-to-use-typed-throws) still imply that one should not use typed throws for this API.

Doug

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 7:56pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/93 "2023-09-27T19:56:02Z")

</div>

Got it, thanks for clarifying.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [September 27, 2023, 7:56pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/94 "2023-09-27T19:56:55Z")

</div>

> [@wadetregaskis](#):
>
> Or at best some completely opaque type that's only `CustomDebugStringConvertible` or somesuch so you can log it but do nothing much else?

i _really, really_ wish `Error` had been designed with logging/reflection in mind, i can’t count how many times i’ve screamed internally because i logged a generic `Error (no description available)` because a dynamic cast or type wrapper somewhere broke the reflection and the more detailed information about the error is simply _unprintable_ even though the error instance might actually contain a lot of detailed information like:

```swift
extension MattelClient
{
    struct Error:Swift.Error
    {
        static
        var namespace:String { "Mattel Error" }

        let code:Int
        let message:String
    }
}

```

and yet it just prints itself as `Error`!

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [September 27, 2023, 7:57pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/95 "2023-09-27T19:57:23Z")

</div>

I wrote a longer reply about how typed throws would've helped here but ultimately I think you're mostly right in this case. The only thing I can think of that typed-throws would've helped here is that it would've forced the authors to more deeply consider how the JSON errors would fit into the overall `DecodingError` rather than simply being able to return their own error type. Whether that would've lead to a better experience or not is unclear, but it may behoove the community to come up with additional guideline around public error types. This applies both to typed-throws and public error types in general so it's probably valuable in general.

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 8:01pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/96 "2023-09-27T20:01:12Z")

</div>

> [@Jon\_Shier](#):
>
> The only thing I can think of that typed-throws would've helped here is that it would've forced the authors to more deeply consider how the JSON errors would fit into the overall `DecodingError` rather than simply being able to return their own error type.

Right, and it's important to not forget the error source sitting in front of the keyboard, in all this. No matter how strict the typing is for errors, humans can still make it break. But there _is_ value in making it hard to do not just outright bad things but also _accidental_ not-great things. I see value here in this proposal for that, like the aforementioned case where simply forcing the person mucking with the JSON decoder to think a little harder about what they were throwing might have avoided this issue (or at least made them update the documentation!).

---

<div class="post-metadata">

**Author:** ![Zollerboy1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/zollerboy1/32/12997_2.png) [@Zollerboy1](https://forums.swift.org/u/Zollerboy1)\
**Post date:** [September 27, 2023, 8:05pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/97 "2023-09-27T20:05:45Z")

</div>

> [@Douglas\_Gregor](#):
>
> To be fair, the change to make `Task.sleep` and `Task.checkCancellation` use typed throws are source-breaking. Maybe we should reconsider those changes, or pull them out into a separate document.

In which ways is that source-breaking? I can only see this very uncommon use-case, but probably there's more examples:

```swift
func foo(_: UInt64) throws {}

var bar = Task.sleep(nanoseconds:)
bar = foo // Works before making Task.sleep use typed throws but errors afterwards

```

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [September 27, 2023, 8:06pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/98 "2023-09-27T20:06:33Z")

</div>

> [@Douglas\_Gregor](#):
>
> It might be... I should probably pull the concurrency API updates into a separate proposal, because there are going to be a lot of them.

I think that makes sense. The concurrency APIs are very broad and would explode this proposal in complexity.

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 27, 2023, 8:17pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/99 "2023-09-27T20:17:02Z")

</div>

> [@FranzBusch](#):
>
> I think that makes sense. The concurrency APIs are very broad and would explode this proposal in complexity.

I tend to agree a separate proposal might make sense, for those reasons. But it might be worth still leaving a note in this one about the extent to which this proposal helps (or doesn't) async code (e.g. the seeming limitations relating to `CancellationError`). For folks to keep in mind when considering this language enhancement overall. I'm strongly in favour of it, but I don't want anyone to think the proposal tries to shove suboptimal bits under the rug.

---

<div class="post-metadata">

**Author:** ![1-877-547-7272](https://avatars.discourse-cdn.com/v4/letter/1/278dde/32.png) [@1-877-547-7272](https://forums.swift.org/u/1-877-547-7272)\
**Post date:** [September 27, 2023, 10:59pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/100 "2023-09-27T22:59:37Z")

</div>

Some of the links in the table of contents don't work — if the section has code in its title, then the link's URL has the wrong fragment. For example, the link to the section "Typed `rethrows`" tries to take me to #typed--rethrows-, but the correct fragment is #typed-rethrows.

@Douglas_Gregor can you fix this?

* * *

It seems that this proposal could help with testing functions that call `fatalError`, `precondition`, and similar functions, [which is actively being discussed on these forums](https://forums.swift.org/t/testing-fatalerror-and-friends/67317/18). Consider this function:

```swift
func requiresAPositiveNumber(_ number: Int) {
    precondition(number > 0)
    // the rest of the function goes here
}

```

Currently, there's no good way to test that this function disallows numbers that aren't positive, since calling it with a nonpositive number would crash the test suite. Even if you were to isolate the test to a separate thread, the crashed thread [could still leak resources and leave locks in a bad state](https://forums.swift.org/t/testing-fatalerror-and-friends/67317/42). However, with this proposal, we could do this:

```swift
protocol ValidationStrategy {
    associatedtype Failure: Error
    static func validationFailure() throws(Failure) -> Never
}

enum PreconditionValidationStrategy: ValidationStrategy {
    static func validationFailure() -> Never {
        preconditionFailure()
    }
}

enum ThrowingValidationStrategy: ValidationStrategy {
    static func validationFailure() throws(ValidationError) -> Never {
        throw ValidationError()
    }
}
struct ValidationError: Error {}

func requiresAPositiveNumber<V: ValidationStrategy>(
    _ number: Int,
    validationStrategy: V.Type = PreconditionValidationStrategy.self
) throws(V.Failure) {
    guard number > 0 else {
        V.validationFailure()
    }
    // the rest of the function goes here
}

```

Production code would call `requiresAPositiveNumber` with `PreconditionValidationStrategy` and the function would act the same as the original function (including its non-throwing signature), but test code could call it with `ThrowingValidationStrategy` and verify that the function correctly rejects non-positive numbers.

---

<div class="post-metadata">

**Author:** ![tikitu](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tikitu/32/4635_2.png) [@tikitu](https://forums.swift.org/u/tikitu)\
**Post date:** [September 28, 2023, 7:01am UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/101 "2023-09-28T07:01:45Z")

</div>

I think my particular mistake shows arguments both ways.

- If the library signature was “throws DecodingError” that would have forced the library authors to “translate” their new error condition into that type. (They might have added a new enum case to do that, or reused an existing one.) I think that’s likely to get them a better API, with more understandable error feedback (e.g. the description string they chose looks uncomfortable in DecodingError context, which is a good thing as it’s actively misleading). Score +1 for typed throws!
- But, I was trying to do something that you really shouldn’t do. (Relying on implementation details of which more-specific-error-cases are sent in which error conditions, which are _not_ documented as a library contract and _not_ a straightforward consequence of the semantics of the errors.) I got bitten by it, and rightfully so. If the library contract was “throws DecodingError” it would actually encourage me to make this mistake, because it gives me a false sense of security. Score -1 for using typed throws _in this particular way_.

(Even switching on the error enum would not have saved me, because it’s perfectly legitimate for the library authors to change the implementation details of which enum case particular situations fall under. Those error cases are designed to provide rich debugging feedback, not to distinguish semantic classes of problems for flow control.)

I definitely see more clearly the risks of applying typed throws where they’re not appropriate, and of spending a lot of time focusing on the attractive nuisance of fine-grained error semantics. I was already doing that, but it’s pretty clear that I shouldn’t have been: that’s less _straightforwardly_ the wrong move if the language gives us better tools to do it with.

[Previous page](https://forums.swift.org/t/pitch-n-1-typed-throws/67496.md?page=4)

[Next page](https://forums.swift.org/t/pitch-n-1-typed-throws/67496.md?page=6)
