Dominance in pattern matching for switch: Spec and Javac inconsistency

Remi Forax forax at univ-mlv.fr
Wed Sep 15 15:55:04 UTC 2021


----- Original Message -----
> From: "Gavin Bierman" <gavin.bierman at oracle.com>
> To: "Ilyas Selimov" <ilyas.selimov at jetbrains.com>
> Cc: "compiler-dev" <compiler-dev at openjdk.java.net>
> Sent: Mardi 14 Septembre 2021 18:02:50
> Subject: Re: Dominance in pattern matching for switch: Spec and Javac inconsistency

> 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.

I disagree, the spec should have a supplementary rule that says that a guard that starts with a type pattern behave like that type pattern with respect to the constants of that type.

This rule allows to bubble up the constants on top of the corresponding type pattern or guards that starts with that type pattern,
making the implementation more efficient (you can test several integer constants with a binary search, or any constants with a hashmap by example).

If we do not have that rule, you can have constants in between guards of the type of the constants, so we have to degrade the implementation of a bunch of if ... equals. 

> 
> Thanks,
> Gavin

regards,
Rémi

> 
>> On 3 Sep 2021, at 06:27, Ilyas Selimov <ilyas.selimov at jetbrains.com> 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