Dominance in pattern matching for switch: Spec and Javac inconsistency

Gavin Bierman gavin.bierman at
Tue Sep 14 16:02:50 UTC 2021

Thanks Ilyas,

Yes, this is a small bug in the spec which is causing your confusion. When it was first drafted it there was only one pattern case label element - a type pattern. By the time we published, there were two more - parenthesised patterns and guarded patterns. The rule didn’t get updated :-(

The rule you read only applies to *type* patterns. We need a couple of extra rules for parenthesised and guarded patterns. 

As it happens the compiler is correct here. We treat a guarded pattern as a subset pattern, unless the guard is a constant expression whose value is true (a rare case!). So, in your example, we see that the first pattern matches *some* integers. We don’t know which ones, so we can’t be sure that it dominates the integer value 1. So the code is correct. 

We could attempt to look at the guards to see what we can infer statically, but I think this unlikely to be a fruitful direction to take.


> On 3 Sep 2021, at 06:27, Ilyas Selimov <ilyas.selimov at> wrote:
> Hello!
> The next code compiles correctly, but it seems to contradict the dominance rules:
> void test(Integer i) {
>   switch (i) {
>     case Integer in && in != null:
>       break;
>     case 1:
>       break;
>     case default:
>       break;  
>   }
> }
> > A switch label that has a pattern case label element p dominates another switch label that has a constant case label element c if either of the following is true:
> > - the type of c is a primitive type and its wrapper class (5.1.7) is a subtype of the erasure of the type of p.
> Maybe the type of p should also be total for the type of selector expression like in the rules for pattern-over-null dominance?
> Thanks,
> Ilyas

More information about the compiler-dev mailing list