Typed throws

IMHO this should get more attention in this proposal, because it solves issues with rethrows and has very likely other use cases as well.

I currently had a problem with rethrowing, where I basically wanted to make a function rethrows, but not based on a parameter. Something like that:

struct Foo {
    let maybeThrowing: () throws -> ()
    
    init(_ maybeThrowing: () throws -> ()) {
        self.maybeThrowing = maybeThrowing
    }

    func bar() rethrows {
        try maybeThrowing()
    }
}

let foo1 = Foo { print("Foo") }
foo1.bar()

let foo2 = Foo { throw Error() }

do {
    try foo2.bar()
} catch {
    print("Error")
}

This obviously does not compile, but if every function implicitly threw Never, we could rewrite it like that (Credits to this answer) :

struct Foo<E: Error> {
    let maybeThrowing: () throws E -> ()
    
    init(_ maybeThrowing: () throws E -> ()) {
        self.maybeThrowing = maybeThrowing
    }

    func bar() throws E {
        try maybeThrowing()
    }
}

var foo1 = Foo { print("Foo") } // Foo<Never>
foo1.bar()

let foo2 = Foo { throw Error() } // Foo<Error>

do {
    try foo2.bar()
} catch {
    print("Error")
}

foo1 = foo2 // error: Cannot assign value of Foo<Error> to variable of type Foo<Never>

Another feature that we would basically get for free, if we made every function throw Never, is this one:

2 Likes