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