# \[Proposal\] Typed throws

**URL:** <https://forums.swift.org/t/proposal-typed-throws/5245>\
**Category:** Discussion\
**Created:** [February 18, 2017, 12:54pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245 "2017-02-18T12:54:21Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 18, 2017, 12:54pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/1 "2017-02-18T12:54:21Z")

</div>

I’ve created a proposal draft, copy-pasting some parts from David Owens’  
proposal.  
Here it is \<[https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289&gt](https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289&gt);  
.

I had to make one addition, which hasn’t been discussed yet. Look at Multiple  
throwing calls  
\<[Draft of "Typed throws" proposal · GitHub](https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289#multiple-throwing-calls-in-one-do-block&gt);  
section. Is this feature controversal, or it’s fine to keep in the  
proposal? Is it feasible from implementation point of view?  
​

---

<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:** [February 18, 2017, 4:37pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/2 "2017-02-18T16:37:25Z")

</div>

Thank you for taking the time to put this proposal together Anton! I really want to see typed throws make it into Swift 4. This will be a very nice feature to have.

I noticed that you included Joe Groff’s idea of replacing `rethrows` by making every function have an error type which is by default `Never` for non-throwing functions and `Error` for throwing functions that do not specify an error type.

I want to urge you to consider updating the proposal to take this direction now rather than later. This is a breaking change which means the longer we wait the harder it is to justify. In fact, I think incorporating the breaking change could increase the chances of it being accepted for Swift 4. Without that it is a purely additive change and those are not being given priority in the Swift 4 release.

> **···**
>
> > On Feb 18, 2017, at 6:54 AM, Anton Zhilin via swift-evolution \<swift-evolution@swift.org\> wrote:
> > 
> > I’ve created a proposal draft, copy-pasting some parts from David Owens’ proposal.  
> > Here it is \<[https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289&gt;\](https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289&gt;%5C).
> > 
> > I had to make one addition, which hasn’t been discussed yet. Look at Multiple throwing calls \<[Draft of "Typed throws" proposal · GitHub](https://gist.github.com/Anton3/3e4081da1adbc6e7a7f377987985c289#multiple-throwing-calls-in-one-do-block&gt); section. Is this feature controversal, or it’s fine to keep in the proposal? Is it feasible from implementation point of view?
> > 
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<div class="post-metadata">

**Author:** ![tali](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tali/32/11346_2.png) [@tali](https://forums.swift.org/u/tali)\
**Post date:** [February 18, 2017, 9:16pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/3 "2017-02-18T21:16:31Z")

</div>

Seconded.  
With typed throwing function parameters, it makes a lot of sense to be able to specify the rethrown type, based on the function given as parameter.

Now some bike-shedding:  
I’m not really happy with the `throws(Type)` syntax, as it is too close to function parameters.  
Why exactly is `throws Type` ambiguous?  
The proposal mentions `Type -\> Result` as potential thrown type, but functions cannot conform to `Error`.  
Maybe we can instruct the parser to just allow simple type names between `throws` and the arrow `-\>`.

If that is not possible, we should at least try to find some visual hints to separate Error type from function parameters.

E.g. we could use brackets (think of: we are specialising the `throws`):

&nbsp;&nbsp;func foo() throws\<MyError\> { … }

— Martin

> **···**
>
> > Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution \<swift-evolution@swift.org\>:
> > 
> > Thank you for taking the time to put this proposal together Anton! I really want to see typed throws make it into Swift 4. This will be a very nice feature to have.
> > 
> > I noticed that you included Joe Groff’s idea of replacing `rethrows` by making every function have an error type which is by default `Never` for non-throwing functions and `Error` for throwing functions that do not specify an error type.
> > 
> > I want to urge you to consider updating the proposal to take this direction now rather than later. This is a breaking change which means the longer we wait the harder it is to justify. In fact, I think incorporating the breaking change could increase the chances of it being accepted for Swift 4. Without that it is a purely additive change and those are not being given priority in the Swift 4 release.

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 19, 2017, 7:32pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/4 "2017-02-19T19:32:24Z")

</div>

Now that I think about it, generic throws does not exactly cover rethrows.  
Firstly, rethrows has semantic information that function itself does not  
throw—it would be lost.

Secondly, rethrows allows a function with multiple throwing function  
parameters to become non-throwing iff all the arguments are non-throwing.  
How would you express it with generics?  
In the proposal, in this case you are required to provide a non-generic  
supertype of all used error types. This type can’t just turn into Never  
automatically.

One solution would be to retain rethrows as an additional attribute.  
It would help with semantic information, and resulting error will be able  
to turn into Never as a special case—now that we know, that this function  
doesn’t throw that error itself.

> **···**
>
> 2017-02-19 0:16 GMT+03:00 Martin Waitz \<tali@admingilde.org\>:
> 
> > Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution \< \> swift-evolution@swift.org\>:
> > 
> > Thank you for taking the time to put this proposal together Anton! I  
> > really want to see typed throws make it into Swift 4. This will be a very  
> > nice feature to have.
> > 
> > I noticed that you included Joe Groff’s idea of replacing `rethrows` by  
> > making every function have an error type which is by default `Never` for  
> > non-throwing functions and `Error` for throwing functions that do not  
> > specify an error type.
> > 
> > I want to urge you to consider updating the proposal to take this  
> > direction now rather than later. This is a breaking change which means the  
> > longer we wait the harder it is to justify. In fact, I think incorporating  
> > the breaking change could increase the chances of it being accepted for  
> > Swift 4. Without that it is a purely additive change and those are not  
> > being given priority in the Swift 4 release.
> > 
> > Seconded.  
> > With typed throwing function parameters, it makes a lot of sense to be  
> > able to specify the rethrown type, based on the function given as parameter.
> 
> ​

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 19, 2017, 7:40pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/5 "2017-02-19T19:40:53Z")

</div>

> Now some bike-shedding:  
> I’m not really happy with the `throws(Type)` syntax, as it is too close to  
> function parameters.  
> Why exactly is `throws Type` ambiguous?  
> The proposal mentions `Type -\> Result` as potential thrown type, but  
> functions cannot conform to `Error`.

Well, it's expected to change with one of the follow-up proposals.

> Maybe we can instruct the parser to just allow simple type names between  
> `throws` and the arrow `-\>`.

The ambiguity here is not so "to compiler" as "to human". We don't want  
people to spend extra time parsing the declaration.

If that is not possible, we should at least try to find some visual hints

> to separate Error type from function parameters.
> 
> E.g. we could use brackets (think of: we are specialising the `throws`):
> 
> func foo() throws\<MyError\> { … }

I personally prefer parentheses, because there is precedence of  
parametrized attributes. I wonder what others think on angle brackets  
option.

> **···**
>
> 2017-02-19 0:16 GMT+03:00 Martin Waitz \<tali@admingilde.org\>:

---

<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:** [February 19, 2017, 7:59pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/6 "2017-02-19T19:59:38Z")

</div>

> Now that I think about it, generic throws does not exactly cover rethrows.  
> Firstly, rethrows has semantic information that function itself does not throw—it would be lost.

Can you elaborate further on what you mean by this?

> Secondly, rethrows allows a function with multiple throwing function parameters to become non-throwing iff all the arguments are non-throwing.  
> How would you express it with generics?  
> In the proposal, in this case you are required to provide a non-generic supertype of all used error types. This type can’t just turn into Never automatically.

This is a very good question. I’m curious if Joe has a solution that doesn’t require introducing any additional features into Swift.

The answer I would like to see (that won’t happen in Swift 4) is to adopt some of the ideas in my value subtyping manifesto, including structural unions (that \*do not\* expose any members, even if there are members that all types have in common). All you would be able to do with such a union is convert from one of its constituent types to the union type and cast back down to one of the constituent types.

Having unions like that would very elegantly solve the problem of a function that needs to throw more than one type. It also covers the case you bring up: `Never | Never | Never` would be the exact same type as `Never`. You would never write out `Never | Never | Never` of course, but in a generic context it’s important that we be able to spell it that way and have it collapse to a simple unordered set of its constituent types.

Use of these structural union types would be discouraged in most cases, but they would be very powerful and useful in specialized contexts. Error handling is one of those contexts. Another is at the boundary of a system when you need to accept a heterogenous collection of a small, fixed set of types (as is discussed in the thread about open and public protocols).

> One solution would be to retain rethrows as an additional attribute.  
> It would help with semantic information, and resulting error will be able to turn into Never as a special case—now that we know, that this function doesn’t throw that error itself.

I'm curious to hear Joe’s thought on this. It’s possible this would be a necessary bridge solution until we have something more permanent as I described above.

> **···**
>
> > On Feb 19, 2017, at 1:32 PM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> 
> > 2017-02-19 0:16 GMT+03:00 Martin Waitz \<tali@admingilde.org \<mailto:tali@admingilde.org\>\>:
> > 
> > > Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution \<swift-evolution@swift.org \<mailto:swift-evolution@swift.org\>\>:
> > > 
> > > Thank you for taking the time to put this proposal together Anton! I really want to see typed throws make it into Swift 4. This will be a very nice feature to have.
> > > 
> > > I noticed that you included Joe Groff’s idea of replacing `rethrows` by making every function have an error type which is by default `Never` for non-throwing functions and `Error` for throwing functions that do not specify an error type.
> > > 
> > > I want to urge you to consider updating the proposal to take this direction now rather than later. This is a breaking change which means the longer we wait the harder it is to justify. In fact, I think incorporating the breaking change could increase the chances of it being accepted for Swift 4. Without that it is a purely additive change and those are not being given priority in the Swift 4 release.
> > 
> > Seconded.  
> > With typed throwing function parameters, it makes a lot of sense to be able to specify the rethrown type, based on the function given as parameter.

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 19, 2017, 8:16pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/7 "2017-02-19T20:16:36Z")

</div>

protocol Default { init() }

func exec(f: () throws -\> Void) rethrows  
{  
&nbsp;&nbsp;&nbsp;&nbsp;try f()  
&nbsp;&nbsp;&nbsp;&nbsp;throw MyError() // error because of rethrows  
}

func exec\<E\>(f: () throws(E) -\> Void) throws(E)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E: Error & Default  
{  
&nbsp;&nbsp;&nbsp;&nbsp;try f()  
&nbsp;&nbsp;&nbsp;&nbsp;throw E() // okay  
}

​

> **···**
>
> 2017-02-19 22:59 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> 
> On Feb 19, 2017, at 1:32 PM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> 
> > Now that I think about it, generic throws does not exactly cover rethrows.  
> > Firstly, rethrows has semantic information that function itself does not  
> > throw—it would be lost.
> > 
> > Can you elaborate further on what you mean by this?

---

<div class="post-metadata">

**Author:** ![Colin\_Barrett](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/colin_barrett/32/1015_2.png) [@Colin\_Barrett](https://forums.swift.org/u/Colin_Barrett)\
**Post date:** [February 22, 2017, 12:42am UTC](https://forums.swift.org/t/proposal-typed-throws/5245/8 "2017-02-22T00:42:03Z")

</div>

> Now that I think about it, generic throws does not exactly cover rethrows.  
> Firstly, rethrows has semantic information that function itself does not  
> throw—it would be lost.

That's not true. Parametric polymorphism guarantees that rethrows and  
polymorphic throw are the same.

For example, you can prove that as a consequence of parametricity that  
there is only one (pure) function in the of the set of all functions with  
the type ``forall A. A -\> A'' and furthermore that it is the identity  
function.

The intuition behind this is that you (meaning the fiction; imagine being a  
function!) cannot construct your own value of "A" since you don't have any  
information about what "A" is. The only place to get an "A" is from your  
argument.

Secondly, rethrows allows a function with multiple throwing function

> **···**
>
> On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution \< swift-evolution@swift.org\> wrote:
> 
> > parameters to become non-throwing iff all the arguments are non-throwing.  
> > How would you express it with generics?  
> > In the proposal, in this case you are required to provide a non-generic  
> > supertype of all used error types. This type can’t just turn into Never  
> > automatically.
> > 
> > One solution would be to retain rethrows as an additional attribute.  
> > It would help with semantic information, and resulting error will be able  
> > to turn into Never as a special case—now that we know, that this function  
> > doesn’t throw that error itself.
> > 
> > 2017-02-19 0:16 GMT+03:00 Martin Waitz \<tali@admingilde.org\>:
> > 
> > Am 18.02.2017 um 17:37 schrieb Matthew Johnson via swift-evolution \< \> swift-evolution@swift.org\>:
> > 
> > Thank you for taking the time to put this proposal together Anton! I  
> > really want to see typed throws make it into Swift 4. This will be a very  
> > nice feature to have.
> > 
> > I noticed that you included Joe Groff’s idea of replacing `rethrows` by  
> > making every function have an error type which is by default `Never` for  
> > non-throwing functions and `Error` for throwing functions that do not  
> > specify an error type.
> > 
> > I want to urge you to consider updating the proposal to take this  
> > direction now rather than later. This is a breaking change which means the  
> > longer we wait the harder it is to justify. In fact, I think incorporating  
> > the breaking change could increase the chances of it being accepted for  
> > Swift 4. Without that it is a purely additive change and those are not  
> > being given priority in the Swift 4 release.
> > 
> > Seconded.  
> > With typed throwing function parameters, it makes a lot of sense to be  
> > able to specify the rethrown type, based on the function given as parameter.
> > 
> > ​  
> > \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> > swift-evolution mailing list  
> > swift-evolution@swift.org  
> > [https://lists.swift.org/mailman/listinfo/swift-evolution](https://lists.swift.org/mailman/listinfo/swift-evolution)

---

<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:** [February 19, 2017, 8:29pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/9 "2017-02-19T20:29:40Z")

</div>

Thanks. There is nothing wrong with this at all. Your second `exec` would not accept a non-throwing function because `Never` cannot conform to `Default`. If it didn’t include the `Default` constraint it would not be able to `throw E()`.

If you remove the `Default` constraint and change `throws(E)` to `throws`, and throw `MyError()` in place of `E()` in both places then it behaves exactly as the first example. We don’t lose any expressivity at all.

This is actually an example of a strength of Joe’s suggestion: the second `exec` is able to throw an error of a type that matches the error that might be thrown by the calling argument `f`. I’m not sure of where this might be useful but it is definitely not possible with `rethrows` while it is possible with Joe’s proposal. We have more flexibility in API design under Joe’s proposal.

You did make a great point about coalescing error types from several different function arguments. That’s an edge case, but the inability to coalesce is indeed a problem that probably needs to be addressed by the typed throws proposal in one way or another (if we don’t go with Joe’s suggestion we would need to specify how `rethrows` behaves in cases like this in some detail).

> **···**
>
> > On Feb 19, 2017, at 2:16 PM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> > 
> > 2017-02-19 22:59 GMT+03:00 Matthew Johnson \<matthew@anandabits.com \<mailto:matthew@anandabits.com\>\>:
> > 
> > > On Feb 19, 2017, at 1:32 PM, Anton Zhilin \<antonyzhilin@gmail.com \<mailto:antonyzhilin@gmail.com\>\> wrote:
> > > 
> > > Now that I think about it, generic throws does not exactly cover rethrows.  
> > > Firstly, rethrows has semantic information that function itself does not throw—it would be lost.
> > 
> > Can you elaborate further on what you mean by this?
> > 
> > protocol Default { init() }
> > 
> > func exec(f: () throws -\> Void) rethrows  
> > {  
> > &nbsp;&nbsp;&nbsp;&nbsp;try f()  
> > &nbsp;&nbsp;&nbsp;&nbsp;throw MyError() // error because of rethrows  
> > }
> > 
> > func exec\<E\>(f: () throws(E) -\> Void) throws(E)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E: Error & Default  
> > {  
> > &nbsp;&nbsp;&nbsp;&nbsp;try f()  
> > &nbsp;&nbsp;&nbsp;&nbsp;throw E() // okay  
> > }

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 20, 2017, 9:58am UTC](https://forums.swift.org/t/proposal-typed-throws/5245/10 "2017-02-20T09:58:39Z")

</div>

Thanks. There is nothing wrong with this at all. Your second `exec` would

> not accept a non-throwing function because `Never` cannot conform to  
> `Default`. If it didn’t include the `Default` constraint it would not be  
> able to `throw E()`.

But that raises another concern. In a previous discussion, it was taken for  
granted that Never should conform to all protocols, because if one obtains  
an instance of Never (and they won’t), then everything is possible. But now  
we say that Never can’t conform to Default, because this would break its  
very invariant. Also it can’t conform to any protocol with static members  
or initializers.

But then basically, Never trick can’t be used when we request anything more  
than Error from generic error type (with static members or initializers).  
So this approach turns out to be more limiting than rethrows.  
Don’t misunderstand me—I love the idea of Never replacing rethrows. Just  
want to make sure we don’t lose anything important by the way.

If you remove the `Default` constraint and change `throws(E)` to `throws`,

> and throw `MyError()` in place of `E()` in both places then it behaves  
> exactly as the first example. We don’t lose any expressivity at all.
> 
> This is actually an example of a strength of Joe’s suggestion: the second  
> `exec` is able to throw an error of a type that matches the error that  
> might be thrown by the calling argument `f`. I’m not sure of where this  
> might be useful but it is definitely not possible with `rethrows` while it  
> is possible with Joe’s proposal. We have more flexibility in API design  
> under Joe’s proposal.

Nice. Whether we can throw the error ourselves depends on our ability to  
create the error.

You did make a great point about coalescing error types from several

> different function arguments. That’s an edge case, but the inability to  
> coalesce is indeed a problem that probably needs to be addressed by the  
> typed throws proposal in one way or another (if we don’t go with Joe’s  
> suggestion we would need to specify how `rethrows` behaves in cases like  
> this in some detail).

​

> **···**
>
> 2017-02-19 23:29 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 22, 2017, 1:10pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/11 "2017-02-22T13:10:39Z")

</div>

How about this:

func bypassRethrows\<E: Error\>(\_ f: () throws(E) -\> ()) throws(E) {  
&nbsp;&nbsp;&nbsp;&nbsp;if let e = (MyError() as Error) as? E {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw e  
&nbsp;&nbsp;&nbsp;&nbsp;}  
}

I obviously can’t “test” this right now, but should work?

> **···**
>
> 2017-02-22 3:42 GMT+03:00 Colin Barrett \<colin@springsandstruts.com\>:
> 
> On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution \< \> swift-evolution@swift.org\> wrote:
> 
> > > Now that I think about it, generic throws does not exactly cover rethrows  
> > > .  
> > > Firstly, rethrows has semantic information that function itself does not  
> > > throw—it would be lost.
> > 
> > That's not true. Parametric polymorphism guarantees that rethrows and  
> > polymorphic throw are the same.
> > 
> > For example, you can prove that as a consequence of parametricity that  
> > there is only one (pure) function in the of the set of all functions with  
> > the type ``forall A. A -\> A'' and furthermore that it is the identity  
> > function.
> > 
> > The intuition behind this is that you (meaning the fiction; imagine being  
> > a function!) cannot construct your own value of "A" since you don't have  
> > any information about what "A" is. The only place to get an "A" is from  
> > your argument.
> 
> ​

---

<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:** [February 20, 2017, 3:23pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/12 "2017-02-20T15:23:52Z")

</div>

> 2017-02-19 23:29 GMT+03:00 Matthew Johnson \<matthew@anandabits.com \<mailto:matthew@anandabits.com\>\>:
> 
> Thanks. There is nothing wrong with this at all. Your second `exec` would not accept a non-throwing function because `Never` cannot conform to `Default`. If it didn’t include the `Default` constraint it would not be able to `throw E()`.
> 
> But that raises another concern. In a previous discussion, it was taken for granted that Never should conform to all protocols

Do you have a pointer to this discussion? I must have missed it.

> , because if one obtains an instance of Never (and they won’t), then everything is possible. But now we say that Never can’t conform to Default, because this would break its very invariant. Also it can’t conform to any protocol with static members or initializers.

It seems highly problematic to me to say that never conforms to any protocol with non-instance requirements.

> But then basically, Never trick can’t be used when we request anything more than Error from generic error type (with static members or initializers). So this approach turns out to be more limiting than rethrows.

Can you elaborate here? If you require a function to throw an error type that has non-instance requirements then you would necessarily be restricting callers to provide a throwing function. It is not possible to express such a function with `rethrows`. You can’t talk about the error type at all. If you could talk about the error type and were able to constrain it in this way `rethrows` would necessarily have to exhibit the same behavior as the generic version. The behavior arises out of the constraint you are applying, not the mechanism by which you forward the type.

> **···**
>
> > On Feb 20, 2017, at 3:58 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> 
> > Don’t misunderstand me—I love the idea of Never replacing rethrows. Just want to make sure we don’t lose anything important by the way.
> > 
> > If you remove the `Default` constraint and change `throws(E)` to `throws`, and throw `MyError()` in place of `E()` in both places then it behaves exactly as the first example. We don’t lose any expressivity at all.
> > 
> > This is actually an example of a strength of Joe’s suggestion: the second `exec` is able to throw an error of a type that matches the error that might be thrown by the calling argument `f`. I’m not sure of where this might be useful but it is definitely not possible with `rethrows` while it is possible with Joe’s proposal. We have more flexibility in API design under Joe’s proposal.
> > 
> > Nice. Whether we can throw the error ourselves depends on our ability to create the error.
> > 
> > You did make a great point about coalescing error types from several different function arguments. That’s an edge case, but the inability to coalesce is indeed a problem that probably needs to be addressed by the typed throws proposal in one way or another (if we don’t go with Joe’s suggestion we would need to specify how `rethrows` behaves in cases like this in some detail).

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 20, 2017, 5:14pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/13 "2017-02-20T17:14:13Z")

</div>

> But that raises another concern. In a previous discussion, it was taken  
> for granted that Never should conform to all protocols
> 
> Do you have a pointer to this discussion? I must have missed it.

Here  
\<[http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt](http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt);  
is the discussion where the idea of “empty” type originated.  
Some messages on the topic ended up being there  
\<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;\](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;%5C).

This \<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt); is the  
earliest mention of usage of this empty type for rethrows I could find.  
Some related messages are here  
\<[http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt](http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt);  
as well.

We called this type NoReturn and meant it to be the \*bottom type\*, i.e.  
subtype of all types, meaning that if you have an instance of NoReturn—which  
can only happen in unreachable sections of code—then you can convert it to  
any type. It should have worked like this:

func fatalError() -\> Never

func divide(a: Int, b: Int) -\> Int {  
&nbsp;&nbsp;&nbsp;&nbsp;if b == 0 {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let n: Never = fatalError()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return n as Int  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;return a / b  
}

I pushed the idea of replacing rethrows with Never, inspired by Haskell.  
Although Haskell doesn’t have static function requirements and initializer  
requirements.

, because if one obtains an instance of Never (and they won’t), then

> everything is possible. But now we say that Never can’t conform to Default,  
> because this would break its very invariant. Also it can’t conform to any  
> protocol with static members or initializers.
> 
> It seems highly problematic to me to say that never conforms to any  
> protocol with non-instance requirements.

Here is an example with instance requirements only:

protocol MakesPizza {  
&nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza  
}  
extension Never : MakesPizza {  
&nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this method will never be called anyway  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;burnThisComputer()  
&nbsp;&nbsp;&nbsp;&nbsp;}  
}

let maestroLaPizza = isHeAtWork ? validMaestro :  
(fatalError("something went wrong") as MakesPizza)  
maestroLaPizza.cook()

In this way, Never can conform to any protocol with only instance  
requirements.

But then basically, Never trick can’t be used when we request anything more

> than Error from generic error type (with static members or initializers).  
> So this approach turns out to be more limiting than rethrows.
> 
> Can you elaborate here? If you require a function to throw an error type  
> that has non-instance requirements then you would necessarily be  
> restricting callers to provide a throwing function. It is not possible to  
> express such a function with `rethrows`. You can’t talk about the error  
> type at all. If you could talk about the error type and were able to  
> constrain it in this way `rethrows` would necessarily have to exhibit the  
> same behavior as the generic version. The behavior arises out of the  
> constraint you are applying, not the mechanism by which you forward the  
> type.

With rethrows approach:

protocol BaseError : Error {  
&nbsp;&nbsp;&nbsp;&nbsp;init()  
}

func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ())  
rethrows(BaseError)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError { ... }

With Never approach, we have to create two separate functions for the same  
effect, because Never does not fit in BaseError:

func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ())  
throws(BaseError)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError {  
&nbsp;&nbsp;&nbsp;&nbsp;// It never actually throws E1() or E2() itself, but this fact  
can't be reflected in the signature  
}

func seq(f: () -\> (), g: () -\> ()) {  
&nbsp;&nbsp;&nbsp;&nbsp;// repeat the body  
}

That’s where loss of information (which I meantioned earlier) hurts: we  
can’t apply magic and say “if E1 and E2 are Never then seq does not throw.  
Because it \*can\* throw anyway.

Well, I’m just repeating myself, at least I gave a bit more complete  
example :)  
​

> **···**
>
> 2017-02-20 18:23 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> 
> > On Feb 20, 2017, at 3:58 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:

---

<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:** [February 22, 2017, 3:39pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/14 "2017-02-22T15:39:14Z")

</div>

> How about this:
> 
> func bypassRethrows\<E: Error\>(\_ f: () throws(E) -\> ()) throws(E) {  
> &nbsp;&nbsp;&nbsp;&nbsp;if let e = (MyError() as Error) as? E {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw e  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> }  
> I obviously can’t “test” this right now, but should work?

No because there are many types that conform to `Error` but are not `E` and the signature says you only throw `E`. You have no way to get an instance of `E` except by catching one thrown by `f` because `Error` does not have any initializers and you don’t have any visibility to anything that provides an `E` in any way except when `f` throws.

I am hoping to have time to write up my analysis of generic rethrowing functions later today. There are some very interesting tradeoffs we need to make.

> **···**
>
> > On Feb 22, 2017, at 7:10 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> 
> > 2017-02-22 3:42 GMT+03:00 Colin Barrett \<colin@springsandstruts.com \<mailto:colin@springsandstruts.com\>\>:
> > 
> > On Sun, Feb 19, 2017 at 2:34 PM Anton Zhilin via swift-evolution \<swift-evolution@swift.org \<mailto:swift-evolution@swift.org\>\> wrote:  
> > Now that I think about it, generic throws does not exactly cover rethrows.  
> > Firstly, rethrows has semantic information that function itself does not throw—it would be lost.
> > 
> > That's not true. Parametric polymorphism guarantees that rethrows and polymorphic throw are the same.
> > 
> > For example, you can prove that as a consequence of parametricity that there is only one (pure) function in the of the set of all functions with the type ``forall A. A -\> A'' and furthermore that it is the identity function.
> > 
> > The intuition behind this is that you (meaning the fiction; imagine being a function!) cannot construct your own value of "A" since you don't have any information about what "A" is. The only place to get an "A" is from your argument.

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 22, 2017, 6:15pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/15 "2017-02-22T18:15:15Z")

</div>

I understand how parametric polymorphism works \*in Haskell\*. But we talk  
about Swift, and there \*is\* a way to get an instance of E. I’ll explain it  
another way:

func bypassRethrows\<E: Error\>(\_ f: () throws(E) -\> ()) throws(E) {  
&nbsp;&nbsp;&nbsp;&nbsp;let error: Error = MyError() // create an instance of `MyError`  
&nbsp;&nbsp;&nbsp;&nbsp;if MyError.self is E.Type { // in case `E` happens to be `MyError`  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let e: E = error as! E // then we've actually created an  
instance of `E`, and we can downcast safely  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw e // voila, acquired an instance of `E`  
&nbsp;&nbsp;&nbsp;&nbsp;}  
}  
let f: () throws MyError -\> () = { }  
try bypassRethrows(f) // actually throws `MyError`,  
without ever calling `f`

What line here seems impossible?

No because there are many types that conform to `Error` but are not `E` and

> the signature says you only throw `E`. You have no way to get an instance  
> of `E` except by catching one thrown by `f` because `Error` does not have  
> any initializers and you don’t have any visibility to anything that  
> provides an `E` in any way except when `f` throws.
> 
> I am hoping to have time to write up my analysis of generic rethrowing  
> functions later today. There are some very interesting tradeoffs we need  
> to make.

​

> **···**
>
> 2017-02-22 18:39 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:

---

<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:** [February 20, 2017, 10:21pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/16 "2017-02-20T22:21:39Z")

</div>

> 2017-02-20 18:23 GMT+03:00 Matthew Johnson \<matthew@anandabits.com \<mailto:matthew@anandabits.com\>\>:
> 
> > But that raises another concern. In a previous discussion, it was taken for granted that Never should conform to all protocols
> 
> Do you have a pointer to this discussion? I must have missed it.
> 
> Here \<[http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt](http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt); is the discussion where the idea of “empty” type originated.  
> Some messages on the topic ended up being there \<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;\](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;%5C).
> 
> This \<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt); is the earliest mention of usage of this empty type for rethrows I could find.  
> Some related messages are here \<[http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt](http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt); as well.
> 
> We called this type NoReturn and meant it to be the bottom type, i.e. subtype of all types, meaning that if you have an instance of NoReturn—which can only happen in unreachable sections of code—then you can convert it to any type. It should have worked like this:
> 
> func fatalError() -\> Never
> 
> func divide(a: Int, b: Int) -\> Int {  
> &nbsp;&nbsp;&nbsp;&nbsp;if b == 0 {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let n: Never = fatalError()  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return n as Int  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;return a / b  
> }  
> I pushed the idea of replacing rethrows with Never, inspired by Haskell. Although Haskell doesn’t have static function requirements and initializer requirements.

Thanks for the links. I scanned through them somewhat quickly and didn’t see anything that specifically said `Never` should conform to all protocols. Did you see that specifically? I only saw mentions of it being a bottom type and therefore a subtype of all types, which I think is a bit different.

I think a big part of the confusion here revolves around the distinction between a type `T` being a subtype of another type `U` and `Type\<T\>` being a subtype of `Type\<U\>` (using the syntax in your metatype refactoring proposal). I’m not an expert in this area, but I suspect that `Never` can be a subtype of all existential types but without requiring it to actually \*conform\* to all protocols. Any non-instance protocol requirements are not available on existentials (afaik).

> > , because if one obtains an instance of Never (and they won’t), then everything is possible. But now we say that Never can’t conform to Default, because this would break its very invariant. Also it can’t conform to any protocol with static members or initializers.
> 
> It seems highly problematic to me to say that never conforms to any protocol with non-instance requirements.
> 
> Here is an example with instance requirements only:
> 
> protocol MakesPizza {  
> &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza  
> }  
> extension Never : MakesPizza {  
> &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this method will never be called anyway  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;burnThisComputer()  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> }
> 
> let maestroLaPizza = isHeAtWork ? validMaestro : (fatalError("something went wrong") as MakesPizza)  
> maestroLaPizza.cook()  
> In this way, Never can conform to any protocol with only instance requirements.

Sure.

> > But then basically, Never trick can’t be used when we request anything more than Error from generic error type (with static members or initializers). So this approach turns out to be more limiting than rethrows.
> 
> Can you elaborate here? If you require a function to throw an error type that has non-instance requirements then you would necessarily be restricting callers to provide a throwing function. It is not possible to express such a function with `rethrows`. You can’t talk about the error type at all. If you could talk about the error type and were able to constrain it in this way `rethrows` would necessarily have to exhibit the same behavior as the generic version. The behavior arises out of the constraint you are applying, not the mechanism by which you forward the type.
> 
> With rethrows approach:
> 
> protocol BaseError : Error {  
> &nbsp;&nbsp;&nbsp;&nbsp;init()  
> }
> 
> func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) rethrows(BaseError)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError { ... }  
> With Never approach, we have to create two separate functions for the same effect, because Never does not fit in BaseError:
> 
> func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) throws(BaseError)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError {  
> &nbsp;&nbsp;&nbsp;&nbsp;// It never actually throws E1() or E2() itself, but this fact can't be reflected in the signature  
> }
> 
> func seq(f: () -\> (), g: () -\> ()) {  
> &nbsp;&nbsp;&nbsp;&nbsp;// repeat the body  
> }  
> That’s where loss of information (which I meantioned earlier) hurts: we can’t apply magic and say “if E1 and E2 are Never then seq does not throw. Because it can throw anyway.
> 
> Well, I’m just repeating myself, at least I gave a bit more complete example :)

Yes, I understood the example and it’s a good one. What I’m wondering is what benefit you actually get from this. There are two places where this default initializer could be used:

1. In `seq` itself. But it seems highly dubious to throw an error you know nothing about. Why does `seq` need the ability to construct an error of the same type as a function given to it without knowing anything more about that error type. Is there a use case for this?  
2. In callers of `seq`. Why would the caller care if the error type that `seq` can throw has a default initializer? Is there a use case for this?

In other words, why do you want to specify that the type of error that might be thrown must have a default initializer? I can’t think of any possible circumstance where this would be valuable.

The same question can be asked of any other static requirements. What are the use cases? These seem highly theoretical to me. Maybe I’m missing something, but if so I would like to see an example of how it is \*used\*, not just how you would need to write an extra overload without `rethrows`.

There is a potentially more practical benefit of keeping rethrows. If a function is declared with `rethrows` we know that the function itself does not throw. It only throws if one of its arguments throw when it invokes them. This is a subtle but important difference. For example, users calling a rethrowing function know that \*they\* have control over whether or not the call \*actually\* throws. The caller might pass a couple of functions that \*can\* throw but in this particular case are known not to throw. That could influence how the caller handles errors in the surrounding scope.

> **···**
>
> > On Feb 20, 2017, at 11:14 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> > 
> > > On Feb 20, 2017, at 3:58 AM, Anton Zhilin \<antonyzhilin@gmail.com \<mailto:antonyzhilin@gmail.com\>\> wrote:

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 20, 2017, 5:19pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/17 "2017-02-20T17:19:38Z")

</div>

I messed up with links a little bit, duplicating one of them. Here  
\<[http://discourse.natecook.com/t/marking-sort-and-sorted-with-rethrows/1764&gt](http://discourse.natecook.com/t/marking-sort-and-sorted-with-rethrows/1764&gt);  
is another one.  
​

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 20, 2017, 11:51pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/18 "2017-02-20T23:51:19Z")

</div>

> Thanks for the links. I scanned through them somewhat quickly and didn’t  
> see anything that specifically said `Never` should conform to all  
> protocols. Did you see that specifically? I only saw mentions of it being  
> a bottom type and therefore a subtype of all types, which I think is a bit  
> different.
> 
> I think a big part of the confusion here revolves around the distinction  
> between a type `T` being a subtype of another type `U` and `Type\<T\>` being  
> a subtype of `Type\<U\>` (using the syntax in your metatype refactoring  
> proposal). I’m not an expert in this area, but I suspect that `Never` can  
> be a subtype of all existential types but without requiring it to actually  
> \*conform\* to all protocols. Any non-instance protocol requirements are not  
> available on existentials (afaik).

I didn't fully understand about metatypes, but otherwise yes indeed.

Yes, I understood the example and it’s a good one. What I’m wondering is

> what benefit you actually get from this. There are two places where this  
> default initializer could be used:
> 
> 1. In `seq` itself. But it seems highly dubious to throw an error you  
> know nothing about. Why does `seq` need the ability to construct an error  
> of the same type as a function given to it without knowing anything more  
> about that error type. Is there a use case for this?  
> 2. In callers of `seq`. Why would the caller care if the error type that  
> `seq` can throw has a default initializer? Is there a use case for this?
> 
> In other words, why do you want to specify that the type of error that  
> might be thrown must have a default initializer? I can’t think of any  
> possible circumstance where this would be valuable.
> 
> The same question can be asked of any other static requirements. What are  
> the use cases? These seem highly theoretical to me. Maybe I’m missing  
> something, but if so I would like to see an example of how it is \*used\*,  
> not just how you would need to write an extra overload without `rethrows`.

Seems highly theoretical to me as well.

There is a potentially more practical benefit of keeping rethrows. If a

> function is declared with `rethrows` we know that the function itself does  
> not throw. It only throws if one of its arguments throw when it invokes  
> them. This is a subtle but important difference. For example, users  
> calling a rethrowing function know that \*they\* have control over whether or  
> not the call \*actually\* throws. The caller might pass a couple of  
> functions that \*can\* throw but in this particular case are known not to  
> throw. That could influence how the caller handles errors in the  
> surrounding scope.

Agreed. Now I lean towards leaving the proposal as is.

> **···**
>
> 2017-02-21 1:21 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> 
> 2017-02-21 1:21 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> 
> > On Feb 20, 2017, at 11:14 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> > 
> > 2017-02-20 18:23 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> > 
> > > On Feb 20, 2017, at 3:58 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> > > 
> > > But that raises another concern. In a previous discussion, it was taken  
> > > for granted that Never should conform to all protocols
> > > 
> > > Do you have a pointer to this discussion? I must have missed it.
> > 
> > Here  
> > \<[http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt](http://discourse.natecook.com/t/idea-change-noreturn-func-f-to-func-f-noreturn/1000&gt);  
> > is the discussion where the idea of “empty” type originated.  
> > Some messages on the topic ended up being there  
> > \<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;\](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt;%5C).
> > 
> > This \<[http://discourse.natecook.com/t/idea-repurpose-void/1406&gt](http://discourse.natecook.com/t/idea-repurpose-void/1406&gt); is the  
> > earliest mention of usage of this empty type for rethrows I could find.  
> > Some related messages are here  
> > \<[http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt](http://discourse.natecook.com/t/draft-change-noreturn-to-unconstructible-return-type/1765/16&gt);  
> > as well.
> > 
> > We called this type NoReturn and meant it to be the \*bottom type\*, i.e.  
> > subtype of all types, meaning that if you have an instance of NoReturn—which  
> > can only happen in unreachable sections of code—then you can convert it to  
> > any type. It should have worked like this:
> > 
> > func fatalError() -\> Never
> > 
> > func divide(a: Int, b: Int) -\> Int {  
> > &nbsp;&nbsp;&nbsp;&nbsp;if b == 0 {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let n: Never = fatalError()  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return n as Int  
> > &nbsp;&nbsp;&nbsp;&nbsp;}  
> > &nbsp;&nbsp;&nbsp;&nbsp;return a / b  
> > }
> > 
> > I pushed the idea of replacing rethrows with Never, inspired by Haskell.  
> > Although Haskell doesn’t have static function requirements and initializer  
> > requirements.
> > 
> > Thanks for the links. I scanned through them somewhat quickly and didn’t  
> > see anything that specifically said `Never` should conform to all  
> > protocols. Did you see that specifically? I only saw mentions of it being  
> > a bottom type and therefore a subtype of all types, which I think is a bit  
> > different.
> > 
> > I think a big part of the confusion here revolves around the distinction  
> > between a type `T` being a subtype of another type `U` and `Type\<T\>` being  
> > a subtype of `Type\<U\>` (using the syntax in your metatype refactoring  
> > proposal). I’m not an expert in this area, but I suspect that `Never` can  
> > be a subtype of all existential types but without requiring it to actually  
> > \*conform\* to all protocols. Any non-instance protocol requirements are not  
> > available on existentials (afaik).
> > 
> > , because if one obtains an instance of Never (and they won’t), then
> > 
> > > everything is possible. But now we say that Never can’t conform to  
> > > Default, because this would break its very invariant. Also it can’t  
> > > conform to any protocol with static members or initializers.
> > > 
> > > It seems highly problematic to me to say that never conforms to any  
> > > protocol with non-instance requirements.
> > 
> > Here is an example with instance requirements only:
> > 
> > protocol MakesPizza {  
> > &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza  
> > }  
> > extension Never : MakesPizza {  
> > &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza {  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this method will never be called anyway  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;burnThisComputer()  
> > &nbsp;&nbsp;&nbsp;&nbsp;}  
> > }
> > 
> > let maestroLaPizza = isHeAtWork ? validMaestro : (fatalError("something went wrong") as MakesPizza)  
> > maestroLaPizza.cook()
> > 
> > In this way, Never can conform to any protocol with only instance  
> > requirements.
> > 
> > Sure.
> > 
> > But then basically, Never trick can’t be used when we request anything
> > 
> > > more than Error from generic error type (with static members or  
> > > initializers). So this approach turns out to be more limiting than  
> > > rethrows.
> > > 
> > > Can you elaborate here? If you require a function to throw an error type  
> > > that has non-instance requirements then you would necessarily be  
> > > restricting callers to provide a throwing function. It is not possible to  
> > > express such a function with `rethrows`. You can’t talk about the error  
> > > type at all. If you could talk about the error type and were able to  
> > > constrain it in this way `rethrows` would necessarily have to exhibit the  
> > > same behavior as the generic version. The behavior arises out of the  
> > > constraint you are applying, not the mechanism by which you forward the  
> > > type.
> > 
> > With rethrows approach:
> > 
> > protocol BaseError : Error {  
> > &nbsp;&nbsp;&nbsp;&nbsp;init()  
> > }
> > 
> > func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) rethrows(BaseError)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError { ... }
> > 
> > With Never approach, we have to create two separate functions for the  
> > same effect, because Never does not fit in BaseError:
> > 
> > func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) throws(BaseError)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError {  
> > &nbsp;&nbsp;&nbsp;&nbsp;// It never actually throws E1() or E2() itself, but this fact can't be reflected in the signature  
> > }
> > 
> > func seq(f: () -\> (), g: () -\> ()) {  
> > &nbsp;&nbsp;&nbsp;&nbsp;// repeat the body  
> > }
> > 
> > That’s where loss of information (which I meantioned earlier) hurts: we  
> > can’t apply magic and say “if E1 and E2 are Never then seq does not  
> > throw. Because it \*can\* throw anyway.
> > 
> > Well, I’m just repeating myself, at least I gave a bit more complete  
> > example :)  
> > ​
> > 
> > Yes, I understood the example and it’s a good one. What I’m wondering is  
> > what benefit you actually get from this. There are two places where this  
> > default initializer could be used:
> > 
> > 1. In `seq` itself. But it seems highly dubious to throw an error you  
> > know nothing about. Why does `seq` need the ability to construct an error  
> > of the same type as a function given to it without knowing anything more  
> > about that error type. Is there a use case for this?  
> > 2. In callers of `seq`. Why would the caller care if the error type that  
> > `seq` can throw has a default initializer? Is there a use case for this?
> > 
> > In other words, why do you want to specify that the type of error that  
> > might be thrown must have a default initializer? I can’t think of any  
> > possible circumstance where this would be valuable.
> > 
> > The same question can be asked of any other static requirements. What are  
> > the use cases? These seem highly theoretical to me. Maybe I’m missing  
> > something, but if so I would like to see an example of how it is \*used\*,  
> > not just how you would need to write an extra overload without `rethrows`.
> > 
> > There is a potentially more practical benefit of keeping rethrows. If a  
> > function is declared with `rethrows` we know that the function itself does  
> > not throw. It only throws if one of its arguments throw when it invokes  
> > them. This is a subtle but important difference. For example, users  
> > calling a rethrowing function know that \*they\* have control over whether or  
> > not the call \*actually\* throws. The caller might pass a couple of  
> > functions that \*can\* throw but in this particular case are known not to  
> > throw. That could influence how the caller handles errors in the  
> > surrounding scope.

---

<div class="post-metadata">

**Author:** ![Anton\_Zhilin](https://avatars.discourse-cdn.com/v4/letter/a/e79b87/32.png) [@Anton\_Zhilin](https://forums.swift.org/u/Anton_Zhilin)\
**Post date:** [February 22, 2017, 6:27pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/19 "2017-02-22T18:27:32Z")

</div>

As a follow-up, here is code that you can test now. It demonstrates the  
same, but with normal function result.

func createArbitrary\<T\>(usingGenerator f: () -\> (T)) -\> T {  
&nbsp;&nbsp;&nbsp;&nbsp;let any: Any = 42 as Any  
&nbsp;&nbsp;&nbsp;&nbsp;if Int.self is T.Type {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let t = any as! T  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return t  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;return f()  
}  
print(createArbitrary(usingGenerator: { return 5 })) //=\> 42

And yes, nobody should do these tricks in production code :P

I understand how parametric polymorphism works \*in Haskell\*. But we talk

> about Swift, and there \*is\* a way to get an instance of E. I’ll explain  
> it another way:
> 
> func bypassRethrows\<E: Error\>(\_ f: () throws(E) -\> ()) throws(E) {  
> &nbsp;&nbsp;&nbsp;&nbsp;let error: Error = MyError() // create an instance of `MyError`  
> &nbsp;&nbsp;&nbsp;&nbsp;if MyError.self is E.Type { // in case `E` happens to be `MyError`  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let e: E = error as! E // then we've actually created an instance of `E`, and we can downcast safely  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw e // voila, acquired an instance of `E`  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> }  
> let f: () throws MyError -\> () = { }  
> try bypassRethrows(f) // actually throws `MyError`, without ever calling `f`
> 
> What line here seems impossible?

​

> **···**
>
> 2017-02-22 21:15 GMT+03:00 Anton Zhilin \<antonyzhilin@gmail.com\>:

---

<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:** [February 21, 2017, 4:00pm UTC](https://forums.swift.org/t/proposal-typed-throws/5245/20 "2017-02-21T16:00:44Z")

</div>

> > Thanks for the links. I scanned through them somewhat quickly and didn’t see anything that specifically said `Never` should conform to all protocols. Did you see that specifically? I only saw mentions of it being a bottom type and therefore a subtype of all types, which I think is a bit different.
> > 
> > I think a big part of the confusion here revolves around the distinction between a type `T` being a subtype of another type `U` and `Type\<T\>` being a subtype of `Type\<U\>` (using the syntax in your metatype refactoring proposal). I’m not an expert in this area, but I suspect that `Never` can be a subtype of all existential types but without requiring it to actually \*conform\* to all protocols. Any non-instance protocol requirements are not available on existentials (afaik).
> 
> I didn't fully understand about metatypes, but otherwise yes indeed.
> 
> > Yes, I understood the example and it’s a good one. What I’m wondering is what benefit you actually get from this. There are two places where this default initializer could be used:
> > 
> > 1. In `seq` itself. But it seems highly dubious to throw an error you know nothing about. Why does `seq` need the ability to construct an error of the same type as a function given to it without knowing anything more about that error type. Is there a use case for this?  
> > 2. In callers of `seq`. Why would the caller care if the error type that `seq` can throw has a default initializer? Is there a use case for this?
> > 
> > In other words, why do you want to specify that the type of error that might be thrown must have a default initializer? I can’t think of any possible circumstance where this would be valuable.
> > 
> > The same question can be asked of any other static requirements. What are the use cases? These seem highly theoretical to me. Maybe I’m missing something, but if so I would like to see an example of how it is \*used\*, not just how you would need to write an extra overload without `rethrows`.
> 
> Seems highly theoretical to me as well.
> 
> > There is a potentially more practical benefit of keeping rethrows. If a function is declared with `rethrows` we know that the function itself does not throw. It only throws if one of its arguments throw when it invokes them. This is a subtle but important difference. For example, users calling a rethrowing function know that \*they\* have control over whether or not the call \*actually\* throws. The caller might pass a couple of functions that \*can\* throw but in this particular case are known not to throw. That could influence how the caller handles errors in the surrounding scope.
> 
> Agreed. Now I lean towards leaving the proposal as is.

I've been continuing to think through these generic rethrowing functions and have identified a problem I think we want to address before submitting a proposal for review. Please hold off until I have a chance to write a post describing the problem and laying out our options.

> **···**
>
> Sent from my iPhone
> 
> > On Feb 20, 2017, at 5:51 PM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:  
> > 2017-02-21 1:21 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> 
> > 2017-02-21 1:21 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> > 
> > > > On Feb 20, 2017, at 11:14 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:
> > > > 
> > > > 2017-02-20 18:23 GMT+03:00 Matthew Johnson \<matthew@anandabits.com\>:
> > > > 
> > > > > > On Feb 20, 2017, at 3:58 AM, Anton Zhilin \<antonyzhilin@gmail.com\> wrote:  
> > > > > > But that raises another concern. In a previous discussion, it was taken for granted that Never should conform to all protocols
> > > > > 
> > > > > Do you have a pointer to this discussion? I must have missed it.
> > > > 
> > > > Here is the discussion where the idea of “empty” type originated.  
> > > > Some messages on the topic ended up being there.
> > > > 
> > > > This is the earliest mention of usage of this empty type for rethrows I could find.  
> > > > Some related messages are here as well.
> > > > 
> > > > We called this type NoReturn and meant it to be the bottom type, i.e. subtype of all types, meaning that if you have an instance of NoReturn—which can only happen in unreachable sections of code—then you can convert it to any type. It should have worked like this:
> > > > 
> > > > func fatalError() -\> Never
> > > > 
> > > > func divide(a: Int, b: Int) -\> Int {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;if b == 0 {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let n: Never = fatalError()  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return n as Int  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;}  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;return a / b  
> > > > }  
> > > > I pushed the idea of replacing rethrows with Never, inspired by Haskell. Although Haskell doesn’t have static function requirements and initializer requirements.
> > > 
> > > Thanks for the links. I scanned through them somewhat quickly and didn’t see anything that specifically said `Never` should conform to all protocols. Did you see that specifically? I only saw mentions of it being a bottom type and therefore a subtype of all types, which I think is a bit different.
> > > 
> > > I think a big part of the confusion here revolves around the distinction between a type `T` being a subtype of another type `U` and `Type\<T\>` being a subtype of `Type\<U\>` (using the syntax in your metatype refactoring proposal). I’m not an expert in this area, but I suspect that `Never` can be a subtype of all existential types but without requiring it to actually \*conform\* to all protocols. Any non-instance protocol requirements are not available on existentials (afaik).
> > > 
> > > > > > , because if one obtains an instance of Never (and they won’t), then everything is possible. But now we say that Never can’t conform to Default, because this would break its very invariant. Also it can’t conform to any protocol with static members or initializers.
> > > > > 
> > > > > It seems highly problematic to me to say that never conforms to any protocol with non-instance requirements.
> > > > 
> > > > Here is an example with instance requirements only:
> > > > 
> > > > protocol MakesPizza {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza  
> > > > }  
> > > > extension Never : MakesPizza {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;func cook() -\> Pizza {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this method will never be called anyway  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;burnThisComputer()  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;}  
> > > > }
> > > > 
> > > > let maestroLaPizza = isHeAtWork ? validMaestro : (fatalError("something went wrong") as MakesPizza)  
> > > > maestroLaPizza.cook()  
> > > > In this way, Never can conform to any protocol with only instance requirements.
> > > 
> > > Sure.
> > > 
> > > > > > But then basically, Never trick can’t be used when we request anything more than Error from generic error type (with static members or initializers). So this approach turns out to be more limiting than rethrows.
> > > > > 
> > > > > Can you elaborate here? If you require a function to throw an error type that has non-instance requirements then you would necessarily be restricting callers to provide a throwing function. It is not possible to express such a function with `rethrows`. You can’t talk about the error type at all. If you could talk about the error type and were able to constrain it in this way `rethrows` would necessarily have to exhibit the same behavior as the generic version. The behavior arises out of the constraint you are applying, not the mechanism by which you forward the type.
> > > > 
> > > > With rethrows approach:
> > > > 
> > > > protocol BaseError : Error {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;init()  
> > > > }
> > > > 
> > > > func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) rethrows(BaseError)  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError { ... }  
> > > > With Never approach, we have to create two separate functions for the same effect, because Never does not fit in BaseError:
> > > > 
> > > > func seq\<E1, E2\>(f: () throws(E1) -\> (), g: () throws(E2) -\> ()) throws(BaseError)  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where E1: BaseError, E2: BaseError {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;// It never actually throws E1() or E2() itself, but this fact can't be reflected in the signature  
> > > > }
> > > > 
> > > > func seq(f: () -\> (), g: () -\> ()) {  
> > > > &nbsp;&nbsp;&nbsp;&nbsp;// repeat the body  
> > > > }  
> > > > That’s where loss of information (which I meantioned earlier) hurts: we can’t apply magic and say “if E1 and E2 are Never then seq does not throw. Because it can throw anyway.
> > > > 
> > > > Well, I’m just repeating myself, at least I gave a bit more complete example :)
> > > 
> > > Yes, I understood the example and it’s a good one. What I’m wondering is what benefit you actually get from this. There are two places where this default initializer could be used:
> > > 
> > > 1. In `seq` itself. But it seems highly dubious to throw an error you know nothing about. Why does `seq` need the ability to construct an error of the same type as a function given to it without knowing anything more about that error type. Is there a use case for this?  
> > > 2. In callers of `seq`. Why would the caller care if the error type that `seq` can throw has a default initializer? Is there a use case for this?
> > > 
> > > In other words, why do you want to specify that the type of error that might be thrown must have a default initializer? I can’t think of any possible circumstance where this would be valuable.
> > > 
> > > The same question can be asked of any other static requirements. What are the use cases? These seem highly theoretical to me. Maybe I’m missing something, but if so I would like to see an example of how it is \*used\*, not just how you would need to write an extra overload without `rethrows`.
> > > 
> > > There is a potentially more practical benefit of keeping rethrows. If a function is declared with `rethrows` we know that the function itself does not throw. It only throws if one of its arguments throw when it invokes them. This is a subtle but important difference. For example, users calling a rethrowing function know that \*they\* have control over whether or not the call \*actually\* throws. The caller might pass a couple of functions that \*can\* throw but in this particular case are known not to throw. That could influence how the caller handles errors in the surrounding scope.
