JDK-8187694 : Add compiler support for local variable type-inference
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 10
  • Submitted: 2017-09-19
  • Updated: 2017-09-26
  • Resolved: 2017-09-26
Related Reports
Blocks :  
CSR :  
Description
Summary
-------

Enhance the Java Language to extend type inference to declarations of local variables with initializers.

Problem
-------

Declarations of the types of local variables are often unnecessary. See [JEP 286](http://openjdk.java.net/jeps/286) for an extended discussion.

Solution
--------

The identifier `var` is removed from the domain of valid type names, and re-interpreted in local variable declarations, `for` loops, and `try`-with-resources statements as an indication that the type of the variable should be inferred.

Inference determines the type of the variable's initializer, as if it were a standalone expression. A sanitization step removes any capture variables from the type by performing an _upward projection_ to a supertype. The result is the type of the variable.

An error occurs if the initializer has the null type, or is a poly expression that requires a target type. An error also occurs if the declaration has an unsupported form (such as a local variable declaration with trailing array dimensions).

Specification
-------------

Proposed changes to the Java Language Specification are attached.
Comments
Joe, thanks for the clarification. Yes, I should make the deletions more explicit. Attached is a version updated with this change (mostly in the grammar rules).
26-09-2017

I'm conditionally approving this request. See below. In 14.14.2 in JLS 9, the grammar the EnhancedForStatement is given as EnhancedForStatement: for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement The new spec lists the new grammar for EnhancedForStatement as EnhancedForStatement: for ( { VariableModifier } LocalVariableType VariableDeclaratorId : Expression ) Statement where LocalVariableType is new text in green. therefore, this is not a correct diff. The old UnannType is not shown in red strikeout text. From what I gather the intention is to replace the old UnannType production in the for loop with the new LocalVariableType, which can be either UnannType or var. Likewise, in 14.20.3 of JLS 9, part of the try-with-resources grammar is Resource: {VariableModifier} UnannType VariableDeclaratorId = Expression and the replacement in the document is { VariableModifier } LocalVariableType VariableDeclaratorId Identifier = Expression where LocalVariableType is green new text and VariableDeclaratorId is red deleted text. The replacement of UnannType with LocalVariableType is not reflected in the diff. Similar issues occur in other productions. The intention of the spec change is clear, replace the old UnannType with LocalVariableType in a number of places and replace Identifier with TypeIdentifier. I'm approving this request conditional on a document showing accurate diffs, including the old productions struck out, is attached to the CSR request.
26-09-2017

For the amended specification, does "Note that some variables declared with var cannot be declared with an explicit type, because the type of the variable is not denotable." in 14.1.1 mean strictly what it says, or does it mean something closer to "the type inferred if you use var might be different than the type you'd have to write to declare a variable yourself to hold the result of the same expression because the inferred type might not be denotable." In other words, there could be some other explicit type, a supertype of the inferred type even if it is an imprecise type like java.lang.Object, that could be used to hold the result of the expression instead. Or are there cases where no denotable supertype exists?
26-09-2017

I've attached an updated spec addressing these comments���notably, it is rebased to JLS 9. A couple of things I did not take any action on: 14.14.2: No change appears necessary. I think you're confused by the line break in the middle of the production? It is not meant to be meaningful. (It appears to be due to a typesetting difference between the PDF and HTML formats.) 6.5, etc.: Can a module be named 'var'? Yes. I haven't tried to enumerate all the things that *can* be named 'var', but rather to identify the special cases that *cannot* be named 'var'. (If I had such a list somewhere, I would add modules to it.)
25-09-2017

The grammatical differences appears to contain some errors. One kind of for statement is listed as for ( { VariableModifier } *LocalVariableType* VariableDeclaratorId where "LocalVariableType" is in green indicating new text. The grammar in both Java SE 8 https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2 and Java SE 9 https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html#jls-14.14.2 lists for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement for the corresponding section. The intention appears to be replacing "UnannType" with "LocalVariableType". If that is the case, please make the appropriate corrections in a new version of the attachment. When noting var c = "x".getClass(); // c has type 'Class<? extends String>' it would be a kindness to readers to note whether or not the special typing rules for Object.getClass are being used by reference: http://download.java.net/java/jdk9/docs/api/java/lang/Object.html#getClass-- One could argue that a null in a try-with-resource statement could be treated as AutoCloseable, but I don't think that is a necessary behavior. With the changes to try-with-resources made in JDK 9 as part of Milling Project Coin, the wording of the AutoCloseable constraints was adjusted. Please update the changes in this request accordingly. Underscore was added as a keyword in 9. Can a module be named "var"? Presumably yes.
25-09-2017

@Jon, the text should at least get an update to describe how var is handled, even if the behavior remains the same as today.
22-09-2017

... but var is a valid name in other contexts. Does SourceVersion have to be more clever?
22-09-2017

Looks like the SourceVersion.isName methods should be updated to handle "var"; the expected behavior would be returning false for "var" under RELEASE_10. I can file and fix the bug for this unless the lvti team wants to handle it.
22-09-2017

What base version of the JLS was used to generate the diffs? The try-with-resources changes are missing the update made in JDK 9: https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html#jls-14.20.3.2 The keywords don't include underscore as in 9: https://docs.oracle.com/javase/specs/jls/se9/html/jls-3.html#jls-3.9 Pending the request until this is sorted out.
22-09-2017

Is there a notion to add javac warnings "You are using ``var'' as a type name, beware!!" in JDK 9 updates? This would be analogous to warnings for the use of underscore as a name added in JDK 8 before the removal of underscore as a valid name in JDK 9.
22-09-2017