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 <[email protected]> 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 <[email protected]>
    *Sent:* 26 January 2023 20:33
    *To:* Angelos Bimpoudis <[email protected]>;
    amber-spec-experts <[email protected]>
    *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

Reply via email to