3 ms·
It’s typed throws specifically. Before Swift 6 a function either could throw nothing or could throw anything, like Java’s “throws Exception”. Now you can mark
by MBCook 1y ago
It’s typed throws specifically.
Before Swift 6 a function either could throw nothing or could throw anything, like Java’s “throws Exception”.
Now you can mark that a function can only throw a specific error type but nothing else, like Java’s “throws MyCustomException”.
Seems you can’t list multiple types. You’d have to have them in a class hierarchy and mark the base type.
What I like about this idea: if a function is marked like this, Swift can tell that a catch block is exhaustive without needing a “catch all” error case. And if the function starts throwing more possibilities than you coded for, e.g. new case added to an enum, you get a compiler error! Not a submarine bug.
- dcrazy 1y agoThat last bit is great for application authors but awful for API designers. :)
- MBCook 1y agoYeah it could be risky. Might be a feature best used inside the library implementation but not exposed in the public interfaces. I’m not sure how this would interact with the API compatibility Swift has. Maybe that would help authors.
- conradev 1y agoThe best API design is likely to erase the public type to the `any Error` existential … … but Swift has also the tooling to declare ABI-stable enums without freezing them. Clients are forced to handle unknown cases.
- jayd16 1y agoWhy do you need to restrict to a single base type to exhaustively catch all listed?
- MBCook 1y agoFrom my reading you can’t say “throws(MyError, BadError, ThirdError)”. So you only have two options. You could use a non-checked throws like before, but we’re assuming you want it checked. Since you can only put one name between those parenthesis, the only way to do all three would be to have a base class and list that. Or at least that’s my understanding. However if you do that and there’s a fourth type called UnwantedError, that’s also valid to throw even though you don’t want to. It’s an interesting limit. I didn’t follow this feature, though I remember hearing about it, so I don’t know why that choose was made.
- Someone 1y ago> the only way to do all three would be to have a base class and list that I think the Swift way would be enum FooError: Error { case myError(MyError) case badError(BadError) case thirdError(ThirdError) } and declare your function as throws(FooError). That forces handlers of those exceptions to consider all cases. Edit: I think there’s a case for having the compiler synthesize that if one writes something like throws(MyError||BadError||ThirdError), but I’m not sure I’d would like to have such magic. Would two functions with such a declaration throw the same type of exception? That might matter if you do stats on exceptions logged, for example)
- MBCook 1y agoIt does work that way, but I was thinking of the case where FooError was one of the three types you wanted to throw. You can also declare errors as structs, so that’s where you could use inheritance.