Summary
Currently the javac's AST for a variable with inferred type (i.e. a variable whose type in the source code is var or elided completely) is weird. This is a proposal to make the AST model more closely adhere to what is written in the source code.
Problem
Having variable v declared with an inferred type, e.g. using one of these cases:
var v = List.of("");
for (var v : List.of("")) {}
Consumer<String> c = v -> {}
the javac's AST model is weird: after parsing, the variable's type is null, and later, it is changed to a full AST corresponding to the inferred type - e.g. List<String>. I.e. the type is filled in the AST as a synthetic tree.
This is problematic for two groups of reasons: it is difficult to work with the AST for the API clients; the observable compiler behavior is unorthogonal in some rare cases.
Working with the AST
At least two problem when working with the AST:
- the code analyzing the AST using the Trees API does not have good means to detect the synthetic tree, except possibly checking positions of the trees
- the positions (esp. the end position) of the synthetic tree is missing
Observable compiler behavior
Consider:
package p1;
public class API {
public static PackagePrivate get() { return null; }
public static Iterable<PackagePrivate> getIterable() { return null; }
}
package p1;
class PackagePrivate {}
And then:
$ cat VarUse.java
import p1.API;
void main() {
var v = API.get();
}
$ javac -d out p1/API.java p1/PackagePrivate.java VarUse.java
$ cat ForEachUse.java
import p1.API;
void main() {
for (var v : API.getIterable()) {}
}
$ javac -d out p1/API.java p1/PackagePrivate.java ForEachUse.java
ForEachUse.java:4: error: PackagePrivate is not public in p1; cannot be accessed from outside package
for (var v : API.getIterable()) {}
^
1 error
I.e. when the inferred type is the same in both cases, and it is inaccessible at the point where var is used. But the compile-time error is reported in one case, but not in the other.
Solution
The AST will be made more stable and will more closely adhere to what is written in the source code. Namely:
- if there is no type in the source code, the variable's type in the AST will be
nullat all points visible from the API, - if the variable is declared using
var, the variable's type in the AST will be a newly-introducedVarTypeTree, with proper start and end positions - otherwise, the variable's type will be the type what is in the source code, as is currently.
The compiler's behavior w.r.t. inferred types will be made consistent. In the current prototype, no errors are produced for the inaccessible types, but that can be changed to always produce the errors if desired.
Specification
Preliminary apidiff is attached as vartype_ast.preliminary.00.zip and is also available here: https://cr.openjdk.org/~jlahoda/8268850/vartype_ast.preliminary.00/
- csr of
-
JDK-8268850 AST model for 'var' variables should more closely adhere to the source code
-
- Open
-