Switch labels (null again), some tweaking

Brian Goetz brian.goetz at oracle.com
Thu Apr 29 14:52:28 UTC 2021


Without diving into the translation details prematurely, I just want to 
note that we *do* want the compiler to "totalize" things for us, 
because, DA.  Suppose we have A permits B, C:

     int x ;
     switch (a) {
         case B(int foo): x = foo; break;
         case C(int bar): x = bar; break;
     }
     // HERE

There is some remainder -- null, D -- but we don't want that remainder 
to leak past the switch; when we get to HERE, we'd like x to be DA, and 
a to have matched one of the patterns.  So the compiler has to insert 
_something_ to handle the remaining cases, even if it is only:

     default: throw new TotalityException("blah blah");

But, the details of code generation are not what M is asking about now 
-- he's asking "if I were the user, could I write a truly covering 
switch?"  And the answer is yes, but the shape of the remainder is 
"spiny" and can get complicated quickly.

> Not necessarily.
>
> First, let's acknowledge that you are moving the discussion from the basic semantics to talk about the translation strategy which touch more the binary compatibility,
> aka, what is the semantics when the view of the world at compile time and at runtime are disagreeing.
>
> There are at least two reasons to let javac emits such cases,
> first like with null as remainder, you have to add a lot of cases once you have sub-patterns, so it will bloat the bytecode,
> then if we insert such cases, it means that we also have a code that throw a specific exception bolt into the bytecode which means that we can not change the binary compatibility story later.
>
> The jobs to implement the binary compatibility semantics is the job of the runtime not the compiler, like with lambdas, where the LambdaMetaFactory does some runtime checks before generating + linking the lambda proxy,
> I expect a SwitchMetafactory to do the same job. This is more flexible and allows the runtime to be updated when the VM change by example, the lambdaMetafactory code was changed with the introduction of hidden classes.
>
> Now, the big question is what binary compatibility semantics we want ?
>
> We can by example throw a subclass of LinkageError upfront during the linking when we detect that the sealed type as more subclasses that the one accessible at compile time, but it means that adding a new subclass to a sealed type is not a binary compatible change anymore. We can delay the detection the an incompatible class until we see one at runtime, so adding a new subclass is a compatible change but calling a switch with an instance of such subclass is not.
>
> There is also the question about the order of the cases, should the order of the cases be validated at runtime or not, by example, if we have B < A at compile time but A < B at runtime with a switch that like case B first and case A second.
>
>> Maurizio
> Rémi



More information about the amber-spec-experts mailing list