@Target mixing TYPE_USE and declaration annotation

Michael Ernst mernst at cs.washington.edu
Thu Oct 24 06:10:51 PDT 2013


You are arguing for forbidding certain combinations of ElementType fields 
in an @Target meta-annotation.  This is something that has never been done 
in the Java spec before.

Your argument is based on one specific use case, but other use cases may 
exist.  I have many times been surprised by how people have come up with 
unanticipated uses for my designs.  I'm reluctant to complicate the 
specification and reduce flexibility and generality, just to prevent one 
specific use case.

I would rather let the authors of annotations and annotation processors 
decide how to use them, what the semantics is, and how to support Java SE 
7 uses if necessary.  The transition affects only a very small number of 
people, and your view of it may be different than other people's view.

Advice about current best practice in using ElementTypes in a @Target 
meta-annotation could go in the ElementType documentation, where it would 
be more appropriate, and more likely to be read, than in the JSR 308 

Also, annotation processors don't "attach" annotations to anything -- they 
merely interpret them.  The annotations are attached to the AST by the 
compiler in a well-defined way, depending on the @Target meta-annotation.

Thanks for the comments!


> Subject: @Target mixing TYPE_USE and declaration annotation
> From: Markus Keller <markus_keller at ch.ibm.com>
> To: type-annotations-spec-comments at openjdk.java.net
> Date: Tue, 22 Oct 2013 20:04:50 +0200
> To finish the series of mails lost in the maligned observers list, I want
> to mention
> http://mail.openjdk.java.net/pipermail/type-annotations-spec-observers/2013-April/000152.html
> The gist is that allowing @Target annotations with a mixture of TYPE_USE
> and declaration elements is not only bad for implementers of annotation
> processors, but also for users of such annotations. I'm still convinced
> that mixing TYPE_USE with other targets should be forbidden.
> Page 20 of 308-20131016.pdf has such an example:
>> -------
> If TA is additionally meta-annotated with @Target(ElementType.FIELD), 
> then
> the term
> @TA java.lang.Object is legal in locations which are both declaration and
> type contexts,
> such as a field declaration @TA java.lang.Object f;. Here, @TA is deemed
> to apply
> to the declaration of f (and not to the type java.lang.Object) because TA
> is applicable
> in the field declaration context.
>> -------
> Because an annotation can only have a single @Target annotation, the
> beginning would better be written as: "If TA is meta-annotated with
> @Target({ElementType.TYPE_USE, ElementType.FIELD}), ...".
> And the example hides the even worse ramifications for array-typed 
> fields:
> @TA Object[] f2;
> The SE 7 APIs consider @TA an annotation on field f2.
> The SE 8 APIs consider @TA also a type annotation on Object (not on the
> field type Object[]!).
> Now what does that mean e.g. for "@Nullable Object[] f2;"? If an
> annotation processor wants to be source-compatible with SE 7 code, then 
> it
> cannot rely on the SE 8 meaning of such a mixed-target annotation!
> Although the 308 spec attaches the type annotation to the type "Object",
> the annotation processor still has to adhere to the legacy meaning and
> must attach it to "Object[]". I.e. it effectively *cannot* make use of 
> the
> added TYPE_USE element type in this case.
> If an annotation provider doesn't care about these corner cases with
> qualified and array types, then he can just switch to @Target(TYPE_USE).
> Otherwise, he should deprecate the old declaration annotation and declare
> a new type annotation.
> The current JSR 308 proposal doesn't tell that mixing target elements is
> considered bad style nor that it is discouraged.
> http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html
> says:
>> Note from the above examples that a programmer is permitted to write can
> write a @Target meta-annotation indicating that an annotation, such as
> @FTAnno or @MTAnno, is both a type annotation and a declaration
> annotation. We have not found an example where such a meta-annotation is
> desirable for a newly-created annotation; although it is legal, it is
> considered bad style. By contrast, when migrating from Java SE 7 and 
> older
> annotation processors to Java SE 8 and newer annotation processors, it 
> may
> be desirable for the annotation to be both a type annotation and a
> declaration annotation, for reasons of backward compatibility.
> The last sentence about migration was only added in the very last
> revision, and it gives a very bad advice that locks annotation providers
> and users into an eternal backwards-compatibility mode.
> Summary: The spec allows a bad style for compatibility reasons, but it
> effectively fails to deliver that promise. Backwards compatibility and
> correct treatment of TYPE_USE exclude each other, and the spec should not
> make it appear like there is a solution.
> If it's too late for this change, then the spec should at least tell that
> mixed-target annotation types are dangerous and discouraged.
> Markus

More information about the type-annotations-spec-experts mailing list