Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

Brian Goetz brian.goetz at oracle.com
Thu Apr 7 19:41:02 UTC 2022



> http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html 
>
>
> Comments welcome!

The execution of an exhaustive|switch|can fail with a linkage error 
(an|IncompatibleClassChangeError|is thrown) if it encounters an instance 
of a permitted direct subclass that was not known at compile time 
(14.11.3 
<http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html#jls-14.11.3>,15.28.2 
<http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html#jls-15.28.2>). 
Strictly speaking, the linkage error is not flagging a binary 
incompatible change of the|sealed|class, but more accurately a/migration 
incompatible/change of the|sealed|class.

I think we should back away from ICCE here as well, and put this in the 
MatchException bucket too.  Then:

  - a switch throws NPE if the operand is null;
  - an _enum switch_ throws ICCE when encountering a novel constant;
  - all other remainder errors are MatchException.

File away for future use, that these clauses will have to be extended to 
include other exhaustive pattern-aware constructs, like let.


        14.11.1 Switch Blocks


The grammar for CaseOrDefaultLabel seems like it could be profitably 
refactored to reflect more of the restrictions:

     CaseOrDefaultLabel
         case (null | CaseConstant) {, CaseConstant }
         case [null, ] Pattern { WhenClause }
         case [null, ] default
         default

and then you don't have to enumerate as many of the restrictions of what 
can combine with what.

It is a compile-time error if a|when|expression has the value|false|.

... is a constant expression and has the value false ?

  *

    A pattern case element/p/is switch compatible with/T/if/p/is
    assignable to type/T/(14.30.3
    <http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html#jls-14.30.3>).


Isn't this cast-convertible?  If the selector is String and the pattern 
is `Object o`, o is not assignable to String, but it is cast-convertible.

A switch label is said to/dominate/another switch label

Can we say that in a pattern switch, default dominates everything, which 
has the effect of forcing the default to the bottom?

if there are values for which both apply and there is not an obvious 
preference

Is this really what we mean?  Don't we really mean that the first one 
matches everything the second one does?

A set of case elements is exhaustive

This is a nit, but couldn't this be its own subsection?  This section is 
getting long and varied.

/T/if/T/is downcast convertible to/U/

Is this right?  Upcast convertibility is OK too -- you can match `Object 
o` to a target of `String`, and vice versa.

If the type/R/is a raw type (4.8 
<https://docs.oracle.com/javase/specs/jls/se18/html/jls-4.html#jls-4.8>) 
then the type/T/must be a raw type, or vice versa; otherwise a 
compile-time error occurs.

Is this the right restriction?  What we want here (for this iteration) 
is that if R is generic, we specify the type parameters. But this is not 
the same thing.  I would think we would want to say here something like 
"if the class of R is a generic class, R cannot be raw".

whose type names/R/

missing a word

 1.

    A switch label that supports a pattern/p//applies/if the value
    matches/p/(14.30.2
    <http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html#jls-14.30.2>).
    If pattern matching completes abruptly then determining which switch
    label applies completes abruptly for the same reason.


I think this is carried over from the previous round?  Or do we not 
resolve total type patterns to any at the top level of a switch?

 2.

    If no|case|label matches but there is a|default|label, then
    the|default|label/matches/.*If neither of these rules apply to any
    of the switch labels in the switch block, then a switch label that
    supports a|default|applies.*


Don't we need a clause that says "if there is no default, a 
MatchException is thrown"?

*If pattern matching completes abruptly then the process of determining 
which switch label applies completes abruptly for the same reason.*

Doesn't it complete abruptly with MatchException?  Or can PM only 
complete abruptly with ME as well?

A type pattern that does not appear as an element in a record component 
pattern list is called a/top-level type pattern/.

For future: "or array component pattern list"

The pattern variable declared by an any pattern has a type, which is a 
reference type.

Is this still true?  What if I have `record R(int x) {}` and `case R(var 
x)`?  The type of x is not a reference type.  Same for `case R(int x)`.

A pattern/p/is said to be/unconditional/at a type/T/if every value of 
type/T/will match/p/(after/p/has been resolved at type/T/(14.30.2 
<http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html#jls-14.30.2>)), 
and is defined as follows:

An any pattern is unconditional at all T?




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20220407/061b4778/attachment-0001.htm>


More information about the amber-spec-experts mailing list