RFR: 8231436: Fix the applicability of a no- at Target annotation type

Joel Borggren-Franck joel.p.borggren-franck at oracle.com
Fri Feb 5 14:44:42 UTC 2021


Some comments inline,

> On 3 Feb 2021, at 19:39, Alex Buckley <alex.buckley at oracle.com> wrote:
> Let me focus first on the design question of what a no- at Target annotation type "means". There's no particular reason why it _shouldn't_ mean "all contexts". Mike gave good reasons why it should mean that. For the corner case of an annotation appearing in one of the ambiguous locations in source code, the annotation will appear in the class file/via reflection exactly as if someone had taken the perfectly legitimate course of spelling out @Target({METHOD, TYPE_USE}) -- the no- at Target case is not a secret door to behavior that's otherwise impossible or undesirable.

I agree that had we done this in one go from scratch, it seems likely that the “all contexts” default for no- at Target annotation would have been chosen.

> (We could have said "all contexts" for a no- at Target annotation type but then added a rule in 9.7.4 to special-case a no- at Target annotation that appears in an ambiguous location, e.g., to compile the annotation as if it was applicable only in declaration contexts. More compatibility with SE 8, but more complexity, and I don't think anyone really wants that.)

FYI this is what ecj does. They allow all contexts but don’t generate type annotation attributes from the ambiguous contexts.

> Turning to the compatibility concern: yes, JDK-8231435 shouldn't have claimed behavioral compatibility. It was my error to not recognize what Mike was saying in "It is a behavior change from the current specification, but a small one that affects poorly-written programs that have no @Target meta-annotation." Still, at the end of the day, it's no more than a small behavioral incompatibility for annotation processors (they may see more type annotations than they did before), and one which was within the power of the annotation type's owner to induce anyway (annotation processors that look for type annotations can reasonably be expected to ignore type annotations in places they don't care about).
> I have cc'd Mike in case he wants to add anything further, but the design intent of "all contexts" still looks reasonable to me.

In isolation yes, “all contexts” makes sense, but so does “all declaration contexts”. What worries me here is that we change the semantics of programs written as far back as 2004. While I don’t think this is an absolute no, we shouldn’t do this lightly, the gain should be substantial, and the risk well quantified. One aspect here is that while annotation interface declarations without @Target might very well be poorly written, it is/was still the only way to specify "all current and future declaration targets”, it is/was also the only alternative with some brevity to specify all current declaration contexts, the alternative being to type out 9 ElementTypes.

An alternative would be to adopt your original proposal, “all current and future declaration contexts”, and adding an ElementType corresponding to this default. This way the question “where are annotations applicable?” would be solved, the user can easily and with brevity opt in to all contexts by using something like “@Target({DECLARATIONS, TYPE_USE})" and the backward compatibility risk is lower. The downside is It would mean more work for us in implementing this.


More information about the compiler-dev mailing list