Typed throws

I’m a bit late here but

At most one type of specific error can be used with a throws .

Is this rule set in stone?

I understand that “sum types” are out of scope but, in my opinion, listing types is not a “sum type” but just, well, a list of types.

I would very much like to have a list of types thrown.

I think it would simplify many use cases, e.g. the family example would not have to be:

enum FamilyError : Error {
   case kid(_ e: KidError)
   case spouse(_ e: SpouseError)
   case cat(_ e: CatError)
}

func callFamily() throws FamilyError -> Family {
    do {
        let kids = try callKids()
        let spouse = try callSpouse()
        let cat = try callCat()
        return Family(kids: kids, spouse: spouse, cat: cat)
    } catch let error as CatError  {
        throw FamilyError.cat(error)
    } catch let error as SpouseError  {
        throw FamilyError.spouse(error)
    } catch let error as KidError{
        throw FamilyError.kid(error)
    }
}

but could be much simpler:

func callFamily() throws CatError, SpouseError, KidError -> Family {
    let kids = try callKids()
    let spouse = try callSpouse()
    let cat = try callCat()
    return Family(kids: kids, spouse: spouse, cat: cat)
}

I understand this just moves the catches to the call side. On the other hand, switching over FamilyError is the same amount of code.

For Result and rethrows, the compiler could use the “natural sum type”: Search the inheritance tree until a type is found that all thrown types conform to (the search is guaranteed to end at Error):

protocol ColoredError: Error { }
class BlueError: ColoredError { }
class DeepBlueError: BlueError { }
class RedError: ColoredError { }

func f() throws BlueError, DeepBlueError, RedError {}

is equal to

func f() -> Result<Void, ColoredError> {}