Multi-catch and exhaustiveness check
Brian Goetz
brian.goetz at oracle.com
Mon Aug 1 14:38:26 UTC 2022
First question: what is the type of `e` in your catch block?
You might think it is the union type MyAbstractException |
MyUncheckedException, but in fact it is the least upper bound (LUB) of
the two, which turns out to be RuntimeException, as per JLS 14.20:
> The declared type of an exception parameter that denotes its type as a
> union with
> alternatives D1 | D2 | ... | Dn is lub(D1, D2, ..., Dn).
So your switch is a switch on a variable of type RuntimeException, and
the switch is obviously not exhaustive. So the compiler is correct.
You might ask: why would we define the type of the catch formal like
this? Well, you have to go back to the context in which multi-catch was
added. This was the Project Coin days, where the scope was very limited
-- including no type system changes -- and the use of LUB in this way
was a trade-off that made it mostly acceptable. The alternative would
have been adding full-blown union types, which would not have been a
small change (see this PhD thesis which outlines what would have been
involved: https://scholarship.rice.edu/handle/1911/103594).
On 8/1/2022 8:28 AM, Thiago Henrique Hupner wrote:
> Hello all!
>
> I've played around with the exhaustiveness check and I'd like to
> discuss whether the following code should compile or it is right not
> to compile.
>
> import java.util.*;
> import java.io.*;
>
> sealed abstract class MyAbstractException extends RuntimeException {
> final static class MyException extends MyAbstractException {}
> }
>
> final class MyUncheckedException extends UncheckedIOException {
> public MyUncheckedException() {
> super(null);
> }
> }
>
> public class SealedException {
> public static void main(String[] args) {
> try {
> throw new MyUncheckedException();
> } catch (MyAbstractException | MyUncheckedException e) {
> switch (e) {
> case MyAbstractException.MyException a -> {}
> case MyUncheckedException b -> {}
> }
> }
> }
> }
>
> As MyUncheckedExceptionh is final, and MyAbstractException.MyException
> is the only implementation available for MyAbstractException, I guess
> it is exhaustive, but the compiler disagrees.
>
> SealedException.java:23: error: the switch statement does not cover
> all possible input values
> switch (e) {
> ^
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20220801/40afd670/attachment-0001.htm>
More information about the amber-dev
mailing list