RFR: 8371683: TYPE_USE annotation on var lambda parameter should be rejected

Jan Lahoda jlahoda at openjdk.org
Fri Feb 20 14:52:00 UTC 2026


On Thu, 19 Feb 2026 19:05:32 GMT, Vicente Romero <vromero at openjdk.org> wrote:

>> Consider this code:
>> 
>> $ cat TA.java
>> import java.lang.annotation.ElementType;
>> import java.lang.annotation.Target;
>> import java.util.List;
>> import java.util.function.Consumer;
>> 
>> @Target(ElementType.TYPE_USE)
>> @interface TA {
>> }
>> class T {
>>     public static void t(List<T> l, Object o) {
>>         for (@TA var v : l) {}                   //JLS 9.7.4.: @TA var v should be a compile-time error
>>         Consumer<String> c = (@TA var v) -> {};  //JLS 9.7.4.: @TA var v should be a compile-time error since JDK 20
>>         boolean b = o instanceof Box(@TA var v); //JLS 9.7.4.: @TA var v should be a compile-time error; compile-time error reported, but a wrong/weird one
>>     }
>> }
>> record Box(T v) {}
>> $ javac TA.java 
>> TA.java:13: error: type annotation @TA is not expected here
>>         boolean b = o instanceof Box(@TA var v); //JLS 9.7.4.: @TA var v should be a compile-time error; compile-time error reported, but a wrong/weird one
>>                                          ^
>>   (to annotate a qualified type, write unnamed package. at TA T)
>> 1 error
>> 
>> 
>> JLS 9.7.4 ("Where Annotations May Appear ") disallows all the type-annotated `var`s:
>> - `for (@TA var v : l) {}` - the type annotation was disallowed since introduction of `var` in JDK 10
>> - `(@TA var v) -> {}` - the type annotation was expressly disallowed in JDK 20 via https://bugs.openjdk.org/browse/JDK-8295807
>> - `Box(@TA var v)` - the type annotation was disallowed since introduction of type-test patterns; an error is produced, but it is a wrong type of error.
>> 
>> The reason is that currently, the applicability check is second-guessing whether or not a given variable symbol is for a `var` variable, but in some cases this guess fails.
>> 
>> This PR fixes the problem by having an explicit flag marking symbols as representing a `var` variable, so that the check can be made reliably. For lambda parameters, the new behavior only applies to source level >= 20, and that (I think) sadly requires one more flag to determine lambda parameters. Luckily, flags for variables are not too scarce.
>> 
>> With this patch, the output for the above example is:
>> 
>> /tmp/JDK-8371683/TA.java:11: error: annotation interface not applicable to this kind of declaration
>>         for (@TA var v : l) {}                   //JLS 9.7.4.: @TA var v should be a compile-time error
>>              ^
>> /tmp/JDK-8371683/TA.java:12: error: annotation interface not applicable to this kind of declaration
>>         Consumer<St...
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java line 5445:
> 
>> 5443: 
>> 5444:     protected JCVariableDecl implicitParameter() {
>> 5445:         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER | Flags.LAMBDA_PARAMETER);
> 
> question shouldn't the new LAMBDA_PARAMETER flag be enough? as it seems to be more specific?

We could only set `LAMBDA_PARAMETER`, but then on all places that currently check for `PARAMETER`, we would need to start to check for `PARAMETER | LAMBDA_PARAMETER`. There's not prohibitively many such cases, so we could do it, but it still seemed sensible top keep the existing flag set and add a new one on top of it to keep their meaning focused.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/29687#discussion_r2833589605


More information about the compiler-dev mailing list