Draft JLS Spec about unnamed patterns and variables
Brian Goetz
brian.goetz at oracle.com
Wed Feb 22 15:45:38 UTC 2023
It's a tricky question, because there's lots of ways to come at it. For
example, we do make a distinction between dead *statements* and dead
code in general, and in particular conditionals can have lots of dead code.
For example, in
if (true || destroyTheWorld()) { ... }
we don't remark that `destroyTheWorld()` is dead code (though fine IDEs
will call our attention with tasteful highlighting). We're pretty
aggressive about avoiding _unreachable statements_, but considerably
less aggressive about dead code in general.
Thought experiment: what if we had union type patterns? Then the case
label `case String _, Integer _` would be like matching the the union
type pattern `(String|Integer) _`:
case Number n: ...
case (String|Integer) _: ...
Would javac then complain that `String|Integer` could be simplified to
just `String` on the bsais of flow analysis? (IntelliJ would, of course.)
I initially thought as Tagir did, but then Gavin turned me around and
reminded me that it was not dead code, but unreachable statements that
we try to avoid. So now I am torn...
On 2/22/2023 10:26 AM, Tagir Valeev wrote:
> Hello!
>
> I think we should consider dead patterns as dead code, so this sample
> should not compile.
>
> With best regards,
> Tagir Valeev
>
> On Wed, Feb 22, 2023, 15:34 Angelos Bimpoudis
> <angelos.bimpoudis at oracle.com> wrote:
>
> Coming back to the topic of dominance for a moment before I
> circulate a revised draft spec.
>
> Dominance is the way of pattern matching to detect/dead
> code/(meaning that code on the RHS of a dominated case will never
> be executed, provably).
>
> Assume the example where|Number|dominates|Integer|--all values
> of|Integer|are going to be matched by a proceeding case,|Number|.
> This is a compile-time error. Additionally notice that all binding
> variables happen to be unused.
>
> |switch (o) { case Number n -> 1; case String s -> 2;
> case Integer i -> 2; } |
>
> 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?
>
>
> Many, thanks,
>
> Aggelos
>
>
> ------------------------------------------------------------------------
> *From:* Brian Goetz <brian.goetz at oracle.com>
> *Sent:* 26 January 2023 20:33
> *To:* Angelos Bimpoudis <angelos.bimpoudis at oracle.com>;
> amber-spec-experts <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, ora*one or
>> more*|case|pattern*s*. Every|case|constant must be either (1)
>> the|null|literal, (2) a constant expression (15.29
>> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29>),
>> or (3) the name of an enum constant (8.9.1
>> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-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, ora*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 (15.29
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.29>),
> or (3) the name of an enum constant (8.9.1
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-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) is available at:
>>
>> 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/20230222/8ceae9cd/attachment-0001.htm>
More information about the amber-spec-experts
mailing list