Overall I really like the simplification of merging pattern variables into locals, just with more complex scopes.  The revised definition of effective finality is very natural.  This will all pay off further when we add pattern assignment statements.

The obvious caveat is that you have to search the entire text for "local variable" and consider whether you need to qualify with "that is not a pattern variable".  I suspect you've already done this.

In 4.12.3, the comment on DA sounds like it doesn't apply to pattern variables.  And strictly, it doesn't, but this would be a good place to mention that the scoping of a pattern variable coincides with where that variable would be DA.  I see this in 4.12.5 but a more general statement where you introduce pattern variables would be nice, even if it is a note rather than normative text.

5.5.  I think of `instanceof` as having two forms:

    o instanceof Type
    o instanceof Pattern

This phrasing ("converted to the type indicated by the second operand") is consistent with the first, but I think needs a few more words to be consistent with the second?  Every pattern has a "principal type" (making up a term); the principal type of a type pattern `T t` is `T`; the principal type of a deconstruction pattern `D(...)` is `D`.  (The definition for other kinds of patterns like constant patterns or declared patterns are straightforward enough to define as needed.)

(I assume the stuff on scoping and operational semantics of pattern matching is unchanged, so I skimmed that.)

The shadowing rules still leave room for "flow refinement" as a later feature, where you have a local:

    Object p;
    if (p instanceof Point p) { ... }

where the latter p is considered a type refinement of the former.  We've discussed this before, and it seems a reasonable feature to leave on the "maybe leave room for later" list, but we surely don't have to do anything about it now.


I have one concern:

The second condition eliminates pointless instances of pattern matching where the expression will always match the pattern. In particular, the|null|literal is not compatible with any type test pattern.

I am not sure I agree with this framing.  We need to separate the semantics of _patterns_ from the semantics of `instanceof`. A total pattern (var x, Object x, total type pattern) _does_ match null.  We may exclude some patterns from `instanceof`, but that doesn't change their semantics.  I think we should get ahead of this, rather than plan on patching it later.

Even more so:

The null reference value does not match any type test pattern.

According to the discussions surrounding switch, this is not true.  The null reference value matches any type pattern _that is total on the static type of the operand_.  Again, we've got to separate the semantics of the type pattern, from what `instanceof` does with a type pattern.  We get several shots at null before we actually match the pattern: we can eliminate some matches statically at compile time, and we can eliminate others by giving semantics to instanceof before we ask "does it match the pattern."  So we should be careful in which of these three buckets we put our null hostility.


Overall, though, I am super-happy with how this spec has landed.  At the beginning, we we a bit fearful of how intrusive it would be; in the end, there is basically just the obvious set of new sections: pattern syntax, pattern scoping, pattern operational semantics.  That the diffs are almost entirely "adding new sections" looks like winning to me.  Further, looking ahead, adding both new kinds of patterns (e.g., deconstruction patterns) and new places that use patterns (e.g., pattern assignment) will have an obvious place to go.





On 10/5/2020 8:53 AM, Gavin Bierman wrote:
Dear all:

A draft of the spec for the Patterns in instanceof feature that we plan to
finalize in JDK 16 is now available:

http://cr.openjdk.java.net/~gbierman/8250623/latest/

[NB: The URL will change once we have a JEP number, and will be announced.]

The changes are the same as those in the second preview that was released in
Java SE 16, except for minor editorial changes and the following:

- To lift the restriction that pattern variables are implicitly final. This
   allows pattern variables to be considered as a strict subset of local
   variables. A number of simplifications to the spec result from this change.

- To make it a compile-time error for an expression of type _S_ to be matched
   against a pattern of type _T_, where _S_ is a subtype of _T_. (This pattern
   match will always succeed and is then pointless. The opposite case, where a
   pattern match will always fail is already a compile-time error.)
Comments welcome!

Gavin

Reply via email to