[pattern-switch] Exhaustiveness

Brian Goetz brian.goetz at oracle.com
Mon Aug 31 16:35:21 UTC 2020


The answer is twofold; one is a correctness argument, and the other is a 
practical one.

1.  Box(null) is part of the remainder of `case Box(Bag(var x))`, and 
should be thrown on if the switch is total.  But ICCE is not an accurate 
description of what happened here; there has not been an incompatible 
class change, but instead simply a putatively total switch combined with 
an "acceptably leaky" set of cases.  The semantics here are "I got a 
value that the user didn't handle, but the user and the compiler made a 
deal that its OK to not handle that value, because its a silly value, so 
this exception serves as notice of that."  That's not ICCE.

You could argue "well, then NPE."  Which is also not quite accurate, 
since no one tried to dereference the null reference.  But it might be 
close enough to get away with.  But then, what about something like 
`case TwoBox(Bag(var x), Shape s)` when confronted with a `new 
TwoBox(null, NovelSubtypeOfShape)`?  The latter smells like ICCE, the 
former like NPE.  Which should win?  We could specify this, but .... 
this brings me to my second answer.

2.  How much effort is it worth spending on coming up with a scheme to 
perfectly classify what exception should be thrown on remainder? And, do 
you have any idea how much JCK is then going to have to spend testing 
all the assertions about the difference of what should be thrown in 
weird nested cases?  And then, what happens when Eclipse implements it 
differently?

Having seen how expensive it to adjudicate spec/JCK challenges ("you 
threw AME when I think the spec says you should have thrown ICCE"), 
we've learned not to create those situations when there is no value to 
doing so.  Yes, we could solve this, but it isn't worth it.  This is not 
where we want to spend our complexity and conformance budgets.

An UnexpectedFrogException is both accurate (you got a value in the 
unhandled remainder) and simpler.  So it wins, because we have bigger 
fish to fry.  (Yes, I know frogs aren't fish.)




On 8/31/2020 11:18 AM, forax at univ-mlv.fr wrote:
>
>     To be clear, I think the sweet spot here is:
>
>      - Legacy enum, string, and box (ESB) switches continue to throw
>     NPE on null;
>      - Total switches on enum (including the current expression
>     switches on enum) throw ICCE on a novel value;
>      - For new switches with remainder:
>        - Continue to throw NPE on unhandled null remainder;
>        - Throw UnexpectedFrogException on any other unhandled remainder.
>
>
> I read this as ICCE not being good enough compare to 
> UnexpectedFrogException and i don't understand why ?
>
> Rémi
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20200831/0fe76ab8/attachment.htm>


More information about the amber-spec-experts mailing list