RFR: JDK15-8236210: javac generates wrong annotation for fields generated from record components

Vicente Romero vicente.romero at oracle.com
Thu Jan 16 21:24:15 UTC 2020

Please review the fix for [1] at [2]. Some background:

Annotations applied to record components are propagated to the 
corresponding record member so if an annotation has target: FIELD, it is 
propagated to the corresponding FIELD, if it has target METHOD, it is 
propagated to the accessor and so on. But at the moment when method 
members are generated there is no enough information to propagate only 
the right annotations. So all the annotations are propagated to all the 
possible locations.

So there is a point when we need to remove all the annotations that are 
not in place before going on with the annotation party. On top of the 
above there is the issue that there is no AST representing record 
components, just symbols so the corresponding field has been holding all 
the annotations and it's metadata has been modified as if it was both a 
field and a record component.

So there are two places where we need to trim annotations from: the 
metadata of the symbol and / or the modifiers in the AST. Whatever is in 
the metadata will be written to the class file, whatever is in the 
modifiers could be see by annotation processors.

The metadata contains both type annotations and declaration annotations. 
Type annotations are all in the right place as they are applicable to 
all the types of the corresponding record members generated by the 
compiler. But we could need to remove declaration annotations. So for 
declaration annotations if they are not applicable to the given record 
member it will be needed to remove them. For the AST modifiers if the 
annotation is not applicable either as type annotation and or 
declaration annotation, only in the last case it will be removed.

So it could be that an annotation is removed as a declaration annotation 
but it is kept in the AST modifier for further inspection by annotation 

For example:

     import java.lang.annotation.*;

     @Target({ElementType.TYPE_USE, ElementType.RECORD_COMPONENT})
     @interface Anno { }

     record R(@Anno String s) {}

just before Enter ends we will have for the case of the generated field:
   - @Anno in the modifier
   - @Anno as a type annotation
   - @Anno as a declaration annotation

the last one should be removed because the annotation has not FIELD as 
target but it was applied as a declaration annotation because the field 
was being treated both as a field and as a record component. Once we 
reach the point when the corresponding annotations have been copied to 
the record component, the field doesn't need to hold annotations that 
are not intended for it anymore. Still @Anno has to be kept in the AST's 
modifiers as it is applicable as a type annotation to the type of the field.


[1] https://bugs.openjdk.java.net/browse/JDK-8236210
[2] http://cr.openjdk.java.net/~vromero/8236210/webrev.00/

More information about the compiler-dev mailing list