Draft JLS Spec about unnamed patterns and variables

Remi Forax forax at univ-mlv.fr
Thu Feb 23 18:53:21 UTC 2023


> From: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> To: "Angelos Bimpoudis" <angelos.bimpoudis at oracle.com>, "Brian Goetz"
> <brian.goetz at oracle.com>, "amber-spec-experts"
> <amber-spec-experts at openjdk.java.net>
> Sent: Thursday, February 23, 2023 7:26:11 PM
> Subject: Re: Draft JLS Spec about unnamed patterns and variables

>> Under this JEP this code could be rewritten blindly into:
>> switch (o) {
>>       case Number _ -> 1;
>>       case String _, Integer _-> 2;
>> }

>> Under the definition of dead code above, the common case that was grouped
>> together, -> 2 , is not dead anymore. It can be reached via *case String _*,
>> Integer _-> 2 . As a result, the code above is correct. It just happens that
>> the sub-pattern Integer _ will never be reachable. This can be a warning but
>> the overall case is correct.

>> An alternative interpretation would be to treat sub-patterns as "dead code".
>> Under that interpretation the second case of the second example would be
>> dominated because there is at least one preceding sub-pattern (or whole case
>> label with one pattern as in this case) that dominates at least one of its
>> sub-patterns ( Integer _ ). That case could be rejected (symmetrically to the
>> first example). This seems restrictive but also a valid direction.

>> So, my question is what would be the pros and cons of each approach?

> Actually, it seems to me that you can rewrite the above as follows, even w/o
> this JEP:

> switch (o) {
>       case Number n -> 1;
>       case String s, Integer i-> 2;
> }

> If you do, the compiler complains, but not because `Integer i` is unreacheable.
> But simply because we have fall-through between patterns.

> This is defined in 14.11.1:

>> t is a compile-time error if there is a statement in a switch block that
>> consists of switch-labeled statement groups for which both of the following are
>> true:

>>     1.

>> It is labeled with a switch label that introduces a pattern variable.
>>     2.

>> There is a statement preceding it in the switch block and that statement can
>> complete normally ( [
>> https://docs.oracle.com/javase/specs/jls/se18/html/jls-14.html#jls-14.22 |
>> 14.22 ] ).

>> This condition is required to exclude the possibility of a switch labeled
>> statement being reached for which a pattern variable declared in its switch
>> label is in scope but without the pattern matching having succeeded. For
>> example, the statement labeled by the switch label supporting the type pattern
>> Integer i could be reached from the preceding statement group, and so the
>> pattern variable i will not be initialized:
> Now, you could make a case that the above restriction is unnecessary if we have
> unnamed pattern binding variables... and _if_ you go down that path, yes, you
> do end up with an issue when it comes to dominance.

> But do we want to change the fall-through restriction?
yes, 
for me a type pattern with an unnamed variable does not introduce a pattern variable, '_' is just a notation for no variable, thus i believe, this rule does not apply. 

> Cheers
> Maurizio
regards, 
Rémi 

>> Many, thanks,

>> Aggelos

>> From: Brian Goetz [ mailto:brian.goetz at oracle.com | <brian.goetz at oracle.com> ]
>> Sent: 26 January 2023 20:33
>> To: Angelos Bimpoudis [ mailto:angelos.bimpoudis at oracle.com |
>> <angelos.bimpoudis at oracle.com> ] ; amber-spec-experts [
>> mailto:amber-spec-experts at openjdk.java.net |
>> <amber-spec-experts at openjdk.java.net> ]
>> Subject: Re: Draft JLS Spec about unnamed patterns and variables
>> Small wording nit... in "an unnamed declaration can be used in place of the
>> following declarations"

>> I'm not sure "in place of" is the right wording; I think you may just want to
>> say "in", since the grammar permits it in all of these places. (What you're
>> really doing here is signalling that there are places the grammar allows it,
>> but the semantics do not; you are going to call these out individually in the
>> appropriate places.)

>> Similar for the second "in place of" in this section.

>> In 14.11.1, I might refactor the text a little further. The second sentence of
>> the first paragraph below is about case constants only, but now comes after you
>> talk about case patterns or case constants:

>>> A case label has either one or more case constants, or a one or more case
>>> pattern s . Every case constant must be either (1) the null literal, (2) a
>>> constant expression ( [
>>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 |
>>> 15.29 ] ), or (3) the name of an enum constant ( [
>>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1
>>> ] ); otherwise a compile-time error occurs. A case label that has a null case
>>> constant may have an optional default .

>>> It is a compile-time error if for any case label with more than one case
>>> patterns, any of its case patterns declares one or more pattern variables.

>> I suggest:

>> A case label has either one or more case constants, or a one or more case
>> pattern s .

>> For a case label with case constants, every case constant must be either (1) the
>> null literal, (2) a constant expression ( [
>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29 |
>> 15.29 ] ), or (3) the name of an enum constant ( [
>> https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.9.1 | 8.9.1
>> ] ); otherwise a compile-time error occurs. A case label that has a null case
>> constant may have an optional default .

>> For a case label with case patterns , it is a compile-time error if any of its
>> case patterns declares one or more pattern variables.

>> I am not sure about the definition of dominance here. If I have:

>> case Integer _, String _: A;
>> case Number _ : B;

>> Number dominates Integer, but it doesn't dominate Integer|String. I think you
>> mean "if at least one of pi..pn dominates *all* of the patterns ri..rm, no?

>> But I'm not even sure if this is the right formulation, because:

>> sealed interface I permits A, B { }
>> record A() implements I {}
>> record B() implements I {}

>> case A _, B _: ...
>> case I i: ...

>> The first case label dominates I. So I think you have to appeal to
>> exhaustiveness:

>> "A case label with case patterns p1...pm dominates another case label with case
>> patterns q1...qm if the set of patterns { p1..pm } dominates each qi", no?

>> You probably have to slightly refactor the second statement about "compile time
>> error if dominance" accordingly.

>> On 1/26/2023 5:36 AM, Angelos Bimpoudis wrote:

>>> Dear experts,

>>> The first draft of the JLS spec about unnamed patterns and variables ( [
>>> https://openjdk.org/jeps/8294349 | https://openjdk.org/jeps/8294349 ] ) is
>>> available at:

>>> [ https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ |
>>> https://cr.openjdk.java.net/~abimpoudis/unnamed/latest/ ]

>>> Comments very much welcomed!
>>> Angelos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20230223/89536198/attachment-0001.htm>


More information about the amber-spec-experts mailing list