# \[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:** 10

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [October 2, 2023, 4:30pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/182 "2023-10-02T16:30:58Z")

</div>

> [@tcldr](#):
>
> At risk of derailing the thread, one further benefit of reducing `rethrows` to syntactic sugar is the precedent it sets for enhancing other effects clauses:
> 
> For example, the idea of a `reasync` clause has [already](https://forums.swift.org/t/a-case-study-for-reasync/64590/2) been [raised](https://forums.swift.org/t/the-latest-information-on-reasync/61801) as a counterpart to `rethrows`, but with the ideas surrounding typed throws it sheds some new light on what could potentially be achieved.

I’ve been thinking about this also. If we’re going to rethink `rethrows` I think it should happen in the context of an effect system that allows us to abstract over effects. My hunch is that this would probably end up looking more like Doug’s reinterpretation of `rethrows` in terms of `throws` than the existing behavior of `rethrows` and consistent semantics across effects is probably more important than the subtle difference with current behavior.

This is obviously a separate topic, but one I would love to see receive some attention. If we had a vision of what a general effect system might look like in Swift it could provide helpful context to this decision. Perhaps it would be useful to continue this discussion in the [existing effects thread](https://forums.swift.org/t/algebraic-effects/38769/25)?

---

<div class="post-metadata">

**Author:** ![tcldr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tcldr/32/24405_2.png) [@tcldr](https://forums.swift.org/u/tcldr)\
**Post date:** [October 2, 2023, 4:32pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/183 "2023-10-02T16:32:51Z")

</div>

> [@Jumhyn](#):
>
> That the language currently allows this is (IMO) straightforwardly a bug that should be fixed.

Yes, it's a bug: runtime exception when called with a non-throwing function.

> [@Jumhyn](#):
>
> Were we proposing _specifically allowing_ your example construction in a `rethrows` function, I think we'd be applying equal or greater scrutiny.

Let's hope we won't do that 😄

While my last post somewhat undermines my point, what I do see here is _very_ similar semantics with ever so _slight_ differences. So while it's true that with determined and purposeful construction one can _legally_ raise an error from `func f<E>(_ g: () throws(E)) -> throws (E)` _without_ calling `g`, it's also true that one can _legally_ transform an Error – perhaps versions down the line – to something the caller wasn't expecting when using `rethrows`.

They're both _legal_. But that doesn't mean API consumers will be expecting them.

These particular aspects of the individual methods seem less like features and more like _emergent properties_. If starting from scratch, I don't think there would be much argument. Take the more general approach offered by typed throws. It supports 99.9% of the use cases of `rethrows` – and offers many more besides.

That's what I'm trying to say when judging one against the other. Looking at them based on their individual merits and zooming out to consider how it fits in with the bigger picture.

So in my opinion, the only argument for _not_ reducing `rethrows` to syntactic sugar is because there is some emergent property that's actually being relied upon and which cannot be supported by typed throws. If that's the case, fair play, it's the only reasonable course of action, but if not, it seems like an indulgence to keep it (as non syntactic sugar) that will needlessly complicate the language.

In any case, I would be reluctant to include a 'typed `rethrows`' – just imagine trying to explain why we need _that_ when we have typed throws.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 2, 2023, 4:39pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/184 "2023-10-02T16:39:25Z")

</div>

> [@tcldr](#):
>
> So while it's true that with determined and purposeful construction one can _legally_ raise an error from `func f<E>(_ g: () throws(E)) -> throws (E)` _without_ calling `g`

What's important to note here, though, and what differs from your sidestep of `rethrows` that is possible today, is that it would _not_ be legal to throw an error when `E == Never` (i.e. when `f` is called with a non-throwing function passed for `g`). This is what makes your 'workaround' particularly problematic, since it means that clients can call `f` without any external error handling, thinking that they are entirely protected from any errors.

---

<div class="post-metadata">

**Author:** ![tcldr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tcldr/32/24405_2.png) [@tcldr](https://forums.swift.org/u/tcldr)\
**Post date:** [October 2, 2023, 4:56pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/185 "2023-10-02T16:56:19Z")

</div>

> [@Jumhyn](#):
>
> What's important to note here, though, and what differs from your sidestep of `rethrows` that is possible today, is that it would _not_ be legal to throw an error when `E == Never` (i.e. when `f` is called with a non-throwing function passed for `g`). This is what makes your 'workaround' particularly problematic, since it means that clients can call `f` without any external error handling, thinking that they are entirely protected from any errors.

A bit lost here: do you mean in the context of what `rethrows` would 'desugar' to, or?

I would _expect_ clients can call `f` without any external error handling if `E == Never`?

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [October 2, 2023, 5:01pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/186 "2023-10-02T17:01:44Z")

</div>

> [@Jumhyn](#):
>
> That the language currently allows this is (IMO) straightforwardly a bug that should be fixed.

How do you ban @tcldr’s example without breaking the documented semantics of `rethrows`, which @wadetregaskis [noted](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/170) specifically allows `rethrows` functions to synthesize and throw their own errors?

---

<div class="post-metadata">

**Author:** ![tcldr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tcldr/32/24405_2.png) [@tcldr](https://forums.swift.org/u/tcldr)\
**Post date:** [October 2, 2023, 5:04pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/187 "2023-10-02T17:04:44Z")

</div>

> [@ksluder](#):
>
> How do you ban @tcldr’s example without breaking the documented semantics of `rethrows`, which @wadetregaskis [noted](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/170) specifically allows `rethrows` functions to synthesize and throw their own errors?

I made [another example](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/175), which was actually a compiler bug rather than legal syntax. But yes, `rethrows` certainly has its own legal quirks besides that (in my opinion).

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [October 2, 2023, 5:05pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/188 "2023-10-02T17:05:16Z")

</div>

It might be helpful to think about how a good solution would look like to achieve the semantics of `rethrows`.  
Let's consider the strictest version (the one @xwu talks about).

```swift
func f(g: () throws -> Void) rethrows

```

`f` throws the exactly same error what `g` throws. Not the other type, not the same type, but the same exact value.  
It means the signature of `f` declares "Data Flow". It describes how values will be passed. It's much more detailed function declaration, than Swift is designed for. (IMO it's too much detailed).  
How may more generalized "Data Flow" declarations look like in signatures of functions?  
One bad thing about `rethrows` is that it doesn't explicitly specify the "source" of the error value.  
Let's fix this:

```swift
func f<E: Error>(g: () throws(a: E) -> Void) throws(a)

```

So, `a` is an arbitrary name for a value of error, that will be thrown by `g`.  
`throws(a: E)` means that the type of error will be `E`, but also defines `a` as a named source.  
`throws(a)` means it will throw only errors sourced from whatever the source `a`.  
It's a stricter declaration than `throws(E)`.  
Under such limitation the following code would be invalid:

```swift
var cache: Any?
func f<E: Error>(g: () throws(a: E) -> Void) throws(a) {
  if let e = cache as? E {
    throw e // error: operand is expected to be sourced by `a`
  }
  do {
    try g()
  } catch {
    cache = error
    throw error
  }
} 

```

And we can generalize this notion to return values as well.  
So we explicitly specify relation between the inner function and the outer function in terms of values.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [October 2, 2023, 5:08pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/189 "2023-10-02T17:08:30Z")

</div>

> [@tcldr](#):
>
> I made [another example](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/175), which was actually a compiler bug rather than legal syntax.

Is it a bug, or is it a necessary consequence of relaxing the semantics of `rethrows` in Swift 3? That change basically requires letting `rethrows` functions `throw` at any point, including by invoking arbitrary `throws` functions/closures.

You could conceive of restricting that ability to `catch` blocks, but then you retroactively ban the implementation I linked to above.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 5:11pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/190 "2023-10-02T17:11:26Z")

</div>

> [@Douglas\_Gregor](#):
>
> Naturally, we would only be able to make such a change to `rethrows` with a major language version. But the result is a simpler language, where `rethrows` is just syntactic sugar for something typed throws naturally expresses.
> 
> Big thanks to @Slava_Pestov for suggesting this simplification.

Thanks for the writeup. To clarify, my suggestion wasn't to eliminate rethrows or change it to this new form in Swift 6, just to not carry over rethrows into the world of typed throws. For untyped throws, it seems that replacing rethrows with a new generic parameter is not only source but ABI breaking, so it would be best to leave rethrows as-is.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 5:15pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/191 "2023-10-02T17:15:10Z")

</div>

> [@tcldr](#):
>
> For me, the bigger issue is that we're not applying the same strict judgement to `rethrows` that we do to the typed throws equivalent. For example, it's fairly trivial to 'break-out' of the intended semantics of `rethrows`, too:

This is absolutely right. See the past discussion here: [Pitch: Fix rethrows checking and add rethrows(unsafe)](https://forums.swift.org/t/pitch-fix-rethrows-checking-and-add-rethrows-unsafe/44863)

Fixing the soundness hole with rethrows Classic™ is a source break, and requires a new escape hatch mechanism to make certain idioms work:

```swift
func f(fn: () throws -> T) rethrows {
  var result: Result<T, Error>? = nil
  someNonThrowingThing {
    do {
      result = .success(try fn()) // call to conditionally-throwing closure here
    } catch {
      result = .failure(error)
  }

  try result.get() // this throws unconditionally from the type checker's POV
}

```

Several libraries already use the local function workaround to make the above type check, so we'd need a `rethrows(unsafe)` to express it, but that's gross.

With typed throws, you don't need the escape hatch at all. Parameterizing everything over E expresses this idiom safely:

```swift
func f<T, E>(fn: () throws(E) -> T) throws(E) {
  var result: Result<T, E>? = nil
  someNonThrowingThing {
    do {
      result = .success(try fn()) // call to closure that throws E
    } catch {
      result = .failure(error)
  }

  try result.get() // if this throws, it throws E, so it's fine
}

```

So in my opinion, we should freeze rethrows as-is, and not try to invent a `rethrows(E)` for typed throws.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 5:27pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/192 "2023-10-02T17:27:56Z")

</div>

> [@xwu](#):
>
> In the case spelled `throws(E)`, `f` may throw when `g` does not throw: for example, `f` might throw for every invocation after the first one where `g` throws. In the case of `rethrows`, this would be impermissible.

I believe that thinking of rethrows as a dynamic property, where the rethrows function throws iff one of the closure arguments throws _at runtime_, is actually less useful. There's no way to observe the stricter dynamic behavior from within the language, nor does it break any semantic guarantees to relax it to the static rule that says the rethrows function can throw _at runtime_ if the _static_ type of one of its arguments was inferred as throws.

---

<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:** [October 2, 2023, 6:53pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/193 "2023-10-02T18:53:09Z")

</div>

> [@ksluder](#):
>
> Is it a bug, or is it a necessary consequence of relaxing the semantics of `rethrows` in Swift 3? That change basically requires letting `rethrows` functions `throw` at any point, including by invoking arbitrary `throws` functions/closures.

It's a compiler bug; it violates [the documented [intended] behaviour](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/declarations#Rethrowing-Functions-and-Methods):

> In addition, the `catch` clause must handle only errors thrown by one of the rethrowing function’s throwing parameters. For example, the following is invalid because the `catch` clause would handle the error thrown by `alwaysThrows()`.

```swift
func alwaysThrows() throws {
    throw SomeError.error
}
func someFunction(callback: () throws -> Void) rethrows {
    do {
        try callback()
        try alwaysThrows() // Invalid, alwaysThrows() isn't a throwing parameter
    } catch {
        throw AnotherError.error
    }
}

```

When support was added for throwing inside a `rethrows` function, in Swift 3, evidently a necessary check was omitted: that the throw-containing catch clause is _only_ catching errors thrown by the closure argument(s) or that the thrown error is itself always caught (and suppressed) before leaving the function.

> [@Slava\_Pestov](#):
>
> I believe that thinking of rethrows as a dynamic property, where the rethrows function throws iff one of the closure arguments throws _at runtime_, is actually less useful. There's no way to observe the stricter dynamic behavior from within the language…

There is. Your throwing closure can record whether it was actually called.

More importantly, it provides guarantees for programmers. If a `rethrows` function throws you _know_ (compiler bugs notwithstanding) that it at least called a throwing closure argument. So in your catch handler (or similar) you can rely on that assumption to e.g. know that your (sole) closure argument executed at least up to its first throw point. That may mean, depending on what you wrote in that closure, that it's guaranteed that some initialisation occurred, that certain things are in certain states, etc. That may well determine what your catch clause has to do to clean up, what program state it may use to try to recover from the error, etc.

> [@Slava\_Pestov](#):
>
> …nor does it break any semantic guarantees to relax it to the static rule that says the rethrows function can throw _at runtime_ if the _static_ type of one of its arguments was inferred as throws.

It's logically self-inconsistent, though. If the function _itself_ can throw - without even _using_ any of the closure arguments - then it should _always_ be able to throw; it cannot matter whether the closure arguments are throwing or not.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 6:57pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/194 "2023-10-02T18:57:32Z")

</div>

> [@wadetregaskis](#):
>
> It's logically self-inconsistent, though. If the function _itself_ can throw - without even _using_ any of the closure arguments - then it should _always_ be able to throw; it cannot matter whether the closure arguments are throwing or not.

It all depends on if you think of throwing as a property of values or of types. I feel that types are a better model, where you can certainly have something like this, even though it's quite silly:

```swift
protocol Initable {
  init()
}

func f<E: Initable & Error>(fn: () throws(E) -> ()) throws(E) {
  try fn() // suppose this actually never throws at runtime
  throw E()
}

```

---

<div class="post-metadata">

**Author:** ![dmt](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmt/32/30830_2.png) [@dmt](https://forums.swift.org/u/dmt)\
**Post date:** [October 2, 2023, 6:58pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/195 "2023-10-02T18:58:49Z")

</div>

> [@Slava\_Pestov](#):
>
> So in my opinion, we should freeze rethrows as-is, and not try to invent a `rethrows(E)` for typed throws.

And what do you think about the existing functions in stdlib? E.g. Sequence.map

---

<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:** [October 2, 2023, 7:11pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/196 "2023-10-02T19:11:41Z")

</div>

> [@Slava\_Pestov](#):
>
> ```swift
> protocol Initable {
> init()
> }
> 
> func f<E: Initable & Error>(fn: () throws(E) -> ()) throws(E) {
> try fn() // suppose this actually never throws at runtime
> throw E()
> }
> 
> ```

I'm not sure what you're getting at with this example. It has no bearing on rethrows…?

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 8:06pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/197 "2023-10-02T20:06:58Z")

</div>

> [@taylorswift](#):
>
> but don’t opaque return types use runtime generics, same as normal generics?

Yes. They can be specialized much like normal generics too, if the opaque type declaration's underlying type is known to the client. For something like embedded Swift, it would still be useful to have opaque return types for the type-level abstraction they provide, even if in the implementation they are always substituted away entirely.

---

<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:** [October 2, 2023, 8:22pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/198 "2023-10-02T20:22:47Z")

</div>

> [@Slava\_Pestov](#):
>
> Yes. They can be specialized much like normal generics too, if the opaque type declaration's underlying type is known to the client. For something like embedded Swift, it would still be useful to have opaque return types for the type-level abstraction they provide, even if in the implementation they are always substituted away entirely.

right, but isn’t this specialization still subject to the normal module-boundary constraints?

---

<div class="post-metadata">

**Author:** ![Alex\_Martini](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alex_martini/32/1383_2.png) [@Alex\_Martini](https://forums.swift.org/u/Alex_Martini)\
**Post date:** [October 2, 2023, 9:11pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/199 "2023-10-02T21:11:42Z")

</div>

That documentation change tracked the following compiler behavior change, implemented by @Lily_Ballard who might be able to share more of the thoughts behind it:

> <https://github.com/apple/swift/issues/43296>
>
> | | |
> |------------------|-----------------|…
> |Previous ID | SR-681 |
> |Radar | None |
> |Original Reporter | @lilyball |
> |Type | Bug |
> |Status | Closed |
> |Resolution | Done |
>         
> \<details\>
> \<summary\>Environment\</summary\>
> 
> Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)  
> Target: x86\_64-apple-darwin15.3.0
> 
> Apple Swift version 2.2 (swiftlang-703.0.6 clang-703.0.16)  
> Target: x86\_64-apple-macosx10.9
> 
> 
> \</details\>
> 
> \<details\>
> \<summary\>Additional Detail from JIRA\</summary\>
> 
> | | |
> |------------------|-----------------|
> |Votes | 0 |
> |Component/s | Compiler |
> |Labels | Bug |
> |Assignee | @lilyball |
> |Priority | |
> 
>    
> 
> md5: 195e8fe56938aa35f00d66470337489b
> 
> \</details\>
> 
> 
> 
> 
> 
> \*\*Issue Description:\*\*
> 
> 
> Given the following code:
> 
> \`\`\` java
> struct MyErr: ErrorType {
> var counter: Int = 0
> }
> func foo\<T\>(@noescape f: () throws -\> T) rethrows -\> T {
> do {
> return try f()
> } catch let err as MyErr {
> throw MyErr(counter: err.counter+1)
> }
> }
> \`\`\`
> 
> It's obvious from reading it that this function can only ever throw if the closure argument throws. But the compiler doesn't recognize this, and reports an error:
> 
> unnamed.swift:8:9: error: a function declared 'rethrows' may only throw if its parameter does
> throw MyErr(counter: err.counter+1)
> ^

> <https://github.com/apple/swift/pull/1280>
>
> A catch block can only be entered if the do block threw an error. In a
> rethrows …function, if the do block throws an error only under rethrows
> conditions, then the catch block can only be entered under rethrows
> conditions, which means the catch block can unconditionally throw and
> it's still safe.
> 
> This enables code that looks like
> 
> \`\`\` swift
> func foo(f: () throws -\> Void) rethrows {
> do {
> try f()
> } catch is SomeError {
> throw OtherError()
> }
> }
> \`\`\`
> 
> Fixes \[SR-681\](https://bugs.swift.org/browse/SR-681).

EDIT: The docs describing the original limitation came from commit [f8a46d52](https://github.com/apple/swift-book/commit/f8a46d52b3c2349ccecf6bc844bbbd723a4abd79), which @Joe_Groff reviewed, and which resolved an issue pointed out via Twitter.

> <https://twitter.com/an0/status/647162697088413700>

---

<div class="post-metadata">

**Author:** ![tcldr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tcldr/32/24405_2.png) [@tcldr](https://forums.swift.org/u/tcldr)\
**Post date:** [October 2, 2023, 9:29pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/200 "2023-10-02T21:29:23Z")

</div>

Interesting. Thanks for this. It seems the original issue on Twitter raised the inability to rethrow an error of the _same_ type (in fact the same error) from a catch clause - I assume in order to perform some kind of unwinding

However, the scope seems to have changed at some point to support throwing _any_ error which altered the semantics significantly.

EDIT: twitter issue does mention an arbitrary error actually although there was a question mark over it during implementation. Specifically from @jrose [[Sema] Allow catch blocks to rethrow errors when safe by lilyball · Pull Request #1280 · apple/swift · GitHub](https://github.com/apple/swift/pull/1280#issuecomment-183175032) And, somewhat ironically, the counter example given in the next comment as to why it should be able to throw arbitrary errors appears to actually throw an Error of the same type.

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [October 2, 2023, 9:35pm UTC](https://forums.swift.org/t/pitch-n-1-typed-throws/67496/201 "2023-10-02T21:35:56Z")

</div>

> [@taylorswift](#):
>
> right, but isn’t this specialization still subject to the normal module-boundary constraints?

IIRC unless you’re building with -enable-library-evolution, opaque types are erased except if the underlying type is less than public, but I could be wrong.

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

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