RFR: 8371155: Type annotations on local variables are classified after the local var initializer has been type checked
Jan Lahoda
jlahoda at openjdk.org
Thu Feb 26 17:54:23 UTC 2026
On Thu, 26 Feb 2026 16:45:15 GMT, Vicente Romero <vromero at openjdk.org> wrote:
>> Consider a type-annotated field like:
>>
>> @TypeAnno Supplier<String> v = () -> "";
>>
>>
>> For this field, the type for both the VariableTree and the lambda is `java.util.function. at TypeAnno Supplier<String>`. The type can be accessed e.g. using `Trees.getTypeMirror`.
>>
>> For local variables, however:
>>
>> {
>> @TypeAnno Supplier<String> v = () -> "";
>> }
>>
>>
>> the type is merely `java.util.function.Supplier<String>`. This is because for fields, the annotations are processed before the main variable type is assigned and before the initializer type is inferred. For local variable, the annotations are processed when the whole class is attributed, and at that point the main variable type is assigned, and the initializer type is already derived, so neither of these reflects the annotation.
>>
>> The proposal here is to organize annotation for variable types earlier, immediately after they are entered. A limitation here is that at that point, some local-variable (sub-)kinds, like exception "parameters" and resource variables, are not yet separated out of the local variables, so `TypeAnnotations` cannot rely solely on `getKind()`, and must also look at other aspects.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java line 490:
>
>> 488: alternatives.add(res);
>> 489: alternatives.addAll(ut.alternatives_field.tail);
>> 490: return new UnionClassType((ClassType) ut.getLub(), alternatives.toList());
>
> question: so the type of a union type could be different depending on the presence or not of type annotations?
The idea is that the "unified" type would be the same (getting `ut.getLub()` from the original type), but the first alternative would be enhanced with the type annotation, as is done for ordinary `ClassType`.
There's `type.tsym.type` conversions happening here (the `UnionClassType` will keep `type.tsym`, and `getLub` will do `tsym.type`), but given exceptions cannot be generic, it seems the type after this cascade should be the same as before it(?).
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/29817#discussion_r2860477628
More information about the compiler-dev
mailing list