TYPE_USE annotations on type parameter declarations

Alex Buckley alex.buckley at oracle.com
Wed Dec 9 01:48:38 UTC 2015


On 12/8/2015 5:09 PM, Michael Ernst wrote:
> I did not expect this code to compile:
>
>     @Target(ElementType.TYPE_USE)
>     @interface TU { }
>
>     // This is surprising:
>     public class TypeUseAtParameter<@TU T> {
>     }
>
> because I thought that a @Target(TYPE_USE) annotation could not be
> written on the declaration of a type parameter.  In fact, javac (from
> JDK 8 or JDK 9) accepts it.  See the attachment for a full, compilable
> test case.
>
> Section 9.6.4.1 says, "There are 16 type contexts (§4.11), all
> represented by the enum constant TYPE_USE of
> java.lang.annotation.ElementType.", and section 4.11 does not include a
> type parameter declaration as one of these locations.
>
> Am I confused, or may there be a problem with javac?

Recall from java-annotation-design.pdf that:

---
ElementType.TYPE_USE stands for all uses of types, plus two special cases.

1. A type annotation (one meta-annotated with 
@Target(ElementType.TYPE_USE)) is permitted to be written anywhere 
@Target(ElementType.TYPE) or @Target(ElementType.TYPE_PARAMETER) would 
permit — that is, on a class, interface, or enum declaration, or on a 
type parameter declaration. Strictly speaking, these are declaration 
sites, not uses of a type. However, it is convenient to write a type 
annotation at a type declaration, as shorthand for applying it at all 
uses. For example, @Interned class MyClass { ... } could indicate that 
all uses of MyClass are interned, even though for other classes some 
instances may be interned and other instances not interned.
---

As a result, JLS8 9.7.4 says:

---
It is a compile-time error if an annotation of type T is syntactically a 
modifier for:

- a class, interface, or enum declaration, but T is not applicable to 
type declarations or type contexts; or an annotation type declaration, 
but T is not applicable to annotation type declarations or type 
declarations or type contexts.

- a type parameter declaration of a generic class, interface, method, or 
constructor, but T is not applicable to type parameter declarations or 
type contexts.
---

These clauses mention "or type contexts" to implement the policy that an 
annotation whose own type has @Target(ElementType.TYPE_USE) can be 
written in locations where you might expect to find only an annotation 
whose own type is @Target(ElementType.TYPE) or 
@Target(ElementType.TYPE_PARAMETER). So, javac is fine.

Unfortunately, while reviewing 9.7.4:

---
A declaration annotation is an annotation that applies to a declaration, 
and whose own type is applicable in the declaration context (§9.6.4.1) 
represented by that declaration.

A type annotation is an annotation that applies to a type (or any part 
of a type), and whose own type is applicable in type contexts (§4.11).
---

I found a hole:

- The annotation @TU is not a "declaration annotation" because while it 
applies to a declaration, its own type TU is not applicable in the 
declaration context represented by the 
class/interface/enum/annotation-type/type-parameter declaration.

- The annotation @TU is not considered a "type annotation" because it 
does not apply to a type use.

This failure to classify the annotation is bad. Let's see what javac 
emits for a TYPE_USE annotation like @TU:

- On a class/interface/enum/annotation-type declaration, javac emits a 
Runtime[In]VisibleAnnotations attribute -- this makes sense as it's 
basically a traditional declaration annotation.

- On a type-parameter declaration, javac emits a 
Runtime[In]VisibleTypeAnnotations attribute -- that's the only way to 
encode the annotation, but still we should regard it as a declaration 
annotation (that's how Core Reflection exposes it).

Consequently, 9.7.4 should add a paragraph:

---
***Additionally, an annotation that applies to either:

- a class, interface, enum, or annotation type declaration, or
- a type parameter declaration of a generic class, interface, method, or 
constructor

and whose own type is applicable in type contexts, is deemed to be a 
declaration annotation.***
---

Alex


More information about the compiler-dev mailing list