JDK-8254235 : Compiler implementation of Pattern Matching for instanceof (Final)
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 16
  • Submitted: 2020-10-08
  • Updated: 2022-05-03
  • Resolved: 2020-11-03
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  

The Java language feature "pattern matching for `instanceof`", currently a second round of preview in JDK 15, is to be made final and permanent in JDK 16. Several, small adjustments to the feature are proposed.


The proposed Java language feature "pattern matching for `instanceof`" has been through two rounds of preview, which has resulted in some feedback. Adjustments based on the feedback should be made to the feature, and it should be made final and permanent.


The following changes have been made to the design of the feature and are taken from the JEP (394):

 * Lift the restriction that pattern variables are implicitly final, to reduce asymmetries between local variables and pattern variables.

 * Make it a compile-time error for a pattern `instanceof` expression to compare an expression of type `S` against a pattern of type `T`, where `S` is a subtype of `T`. (This `instanceof` expression will always succeed and is then pointless. The opposite case, where a pattern match will always fail, is already a compile-time error.)

The following changes address implementation improvements: 

 * The Trees API has been modified so that `BindingPatternTree` contains a `VariableTree` that declares the actual binding variable. This is to improve consistency of the API.

 * The feature is made non-preview, including removing preview warnings from modelling APIs.


The draft specification is attached and is also available for convenience <a href="http://cr.openjdk.java.net/~jlahoda/8250625/jep394/jep394-20201026/specs/patterns-instanceof.html">here</a>. The specification draft enumerates the more significant changes in the introduction, which can be summarized as follows:

 * To support non-final binding variables: changes primarily to sections 4.11 and 4.12.3, and also a slight change to the grammar for type test patterns in section
 * To ensure the compile-time error for expression type being a subtype of the pattern type: changes to section 15.20.2
 * Some refactoring of the description of the semantics of pattern instanceof:  changes to sections 15.20.2 and 14.30.3

The specdiff of the API adjustment is attached and is also available for convenience here: http://cr.openjdk.java.net/~jlahoda/8250625/specdiff.01/overview-summary.html.
[~darcy] Some changes were made to the spec in the review process. Latest version and a diff file attached for the record. The only semantic change is in allowing final modifier for pattern variables. This is covered by another bug ( https://bugs.openjdk.java.net/browse/JDK-8257759). The rest of the changes are essentially cosmetic - we took the opportunity to tidy up and unify existing treatment of local variables.

Thanks for the update; moving to Approved.

Recent changes: the specification has been updated to fix the mistakes Joe and Vicente found. The implementation was modified to drop the old preview methods from BindingPatternTree.

Thanks Vicente! Yes, will update.

the spec says at ` Conditional-And Operator &&`: "Pattern variables are implicitly final by design" I guess this needs to be updated right?

~darcy: Well spotted! Yes, this is now imprecise. It needs to read "Pattern variables differ from other local variables in that they are automatically initialized to a value given by the result of pattern matching (14.30.3)."

[~jlahoda] and [~gbierman], note that section 6.3 of the JLS changes states " Pattern variables differ from other local variables in that they can only be assigned a value by pattern matching (14.30.3)." Is this an inconsistency in the spec?

Thanks Joe! Regarding the deprecations in BindingPatternTree, I was somewhat on the fence. Yes, we can remove the methods, but then I was thinking this is a reflective API, which we expect users might use even without --enable-preview, and there is no very strong reason to remove the methods (as we had for example with the BreakTree->YieldTree conversion, where the original AST shape couldn't be reasonably kept). Not really a strong opinion, I believe we have three options: * remove the methods * keep the methods, deprecated for removal, remove in a few releases * keep the methods, deprecated (possibly deprecate for removal later) Which would you prefer? Regarding pattern variables not being final, with the new spec, they can be assigned. I.e. this is now valid: ``` if (o instanceof String s) { s = ""; //not effectivelly final here } ``` So, the binding variable is definitely assigned when it is introduced, may be effectively final (if not re-assigned): ``` if (o instanceof String s) { Runnable r = () -> System.err.println(s); //effectively final here } ``` But it can be also re-assigned (as in the first example). This is consistent with e.g. catch parameter handling, i.e.: ``` catch (Exception e) { e = null; //can re-assign, not effectively final } ``` vs. ``` catch (Exception e) { Runnable r = () -> System.err.println(e); //effectively final here } ```

Moving to Provisional. Should the methods deprecated in BindingPatternTree instead be removed as there is less of a compatibility expectation for a preview feature? For "Lift the restriction that pattern variables are implicitly final, to reduce asymmetries between local variables and pattern variables." since the pattern variables cannot be directly assigned, are they effectively final?