RFR: 8358604: Trees for `var` do not have end positions
Archie Cobbs
acobbs at openjdk.org
Tue Jun 10 14:34:28 UTC 2025
On Thu, 5 Jun 2025 21:14:03 GMT, Archie Cobbs <acobbs at openjdk.org> wrote:
> The compiler replaces `var` nodes with synthetic tree nodes representing the inferred type. Previously, these new synthetic nodes were not being assigned either starting or ending source code positions.
>
> [JDK-8329951](https://bugs.openjdk.org/browse/JDK-8329951) added starting positions, but not ending positions. This PR adds ending positions, and fixes some related bugs discovered in the research process:
>
> * For a declaration like `final var x`, the fix for [JDK-8329951](https://bugs.openjdk.org/browse/JDK-8329951) was returning a starting position incorrectly pointing to `final` instead of `var`.
> * A declaration like `final var x` was correctly starting at `final` for normal declarations, but incorrectly starting at `var` for a lambda parameter declarations.
> * `JCVariableDecl.declaredUsingVar()` was incorrectly returning `false` for `var` variable declarations in record deconstruction patterns (thanks to @cushon for reporting this)
>
> Background: When a `var`is parsed or a variable is implicitly typed such as a lambda parameter, `JCVariableDecl.vartype` is set to null until the type can be inferred. This causes various problems when trying to determine the starting position of (a) the declaration's type, when `var` is used, because the source position of the `var` has been lost forever (especially if there are also modifiers); and (b) the starting position of the declaration itself, when there are no modifiers, because normally that's computed from the start position of `JCVariableDecl.vartype`, which is (sometimes) null. Previously there was a field `JCVariableDecl.startPos` which was put there to workaround problem (b), but that workaround was being applied even when there _were_ modifiers, which is wrong. Etc.
>
> This patch attempts to clarify things and includes the following changes:
>
> * Make a `var`'s starting source position properly recoverable from a `JCVariableDecl` even while `vartype` is null.
> * Fix the three bugs mentioned above.
> * Make `TreeMaker.at()` capable of configuring both the starting and ending position; do some minor cleanup/refactoring.
> * Set ending positions for the synthetic tree nodes that replace `var`
> * Pretty print `var` as `var` instead of `/*missing*/` (drive-by improvement)
> * Add more regression test coverage
> I guess I would like to understand the rationale for adding the end position for the type....there's a question why this specific synthetic tree should have an end position, while the other shouldn't.
@cushon is better positioned (no pun intended) to answer that question than me. In the issue, this rationale is given:
> The end positions can be retrieved using `com.sun.source.util.SourcePositions#getEndPosition` (e.g. by javac plugins), and end positions are available for explicitly typed local variables, so it would be helpful if these synthetic types also recorded an end position for consistency.
Re:
> Also, currently the missing end position is used as a "marker" for synthetic trees. Not particularly nice, but given the synthetic trees are/were (I think) considered a workaround.
I didn't realize that lack of end position was being overloaded in that way. But overloaded by whom? Is this an "official" thing per the API, or just a workaround currently being used in practice by some 3rd party tools?
> When the tree has an end position, how will the Trees API clients find out this tree is synthetic?
I don't know how frozen the Trees API is, but it seems like the most straightforward answer to that would be for us to expose the type of declaration (explicit, implicit, or `var`) directly via this API via some new property. Is that an option?
-------------
PR Comment: https://git.openjdk.org/jdk/pull/25664#issuecomment-2959490988
More information about the compiler-dev
mailing list