Syntax for annotations on receiver type parameters

2 views
Skip to first unread message

Michael Ernst

unread,
Dec 2, 2009, 10:30:37 PM12/2/09
to jsr308-discuss
JSR 308 does not support annotations on receiver type parameters. Section
D.2.1 of the specification notes this as a needed extension. I'd like to
get feedback about the syntax for such an annotation.

You can read section D.2.1 at
http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html#receiver-type-parameter-annotations
but I'll quote it here for convenience:


D.2.1 Annotations on receiver type parameters

It is sometimes desirable for a method to express constraints on the
generic parameters of the receiver, just as is already possible for other
formal parameters. This is not currently possible (see the grammar of
Section 5).

For example, consider the Collection.toArray() method, which returns an
array of objects, where the objects have the same annotation as the
elements of the receiver. A natural way to write this would be

public @PolyNull Object[] toArray() ArrayList<@PolyNull E> { ... }

except that this is illegal syntax: "ArrayList<@PolyNull E>" in the
receiver position is not legal. It is permissible to write an annotation on
the raw type of the receiver, as in

public Object[] toArray() @Readonly { ... }

but not on the receiver's type parameters.

Here are other examples:

interface List<T> {
// The size() method changes neither the receiver nor any of the elements.
public int size() @Readonly List<@Readonly T> { ... }
}
class MyMap<T,U> {
// The method requires that the map's values be non-null, but the keys may be arbitrary.
public void requiresNonNullValues() MyMap<T, @NonNull U> { ... }
}




A problem in choosing a syntax is that the receiver type is implicit, so
there is no particularly good place to put these annotations. But, the
annotations are necessary in some circumstances. (In other circumstances,
they won't be written, so they won't get in the way.)


Section D.2.1 uses this proposed syntax:
public @PolyNull Object[] toArray() ArrayList<@PolyNull E> { ... }

A previous proposal omitted the type names:
public @PolyNull Object[] toArray() <@PolyNull> { ... }
This is terser, but also potentially harder to understand.

Another proposal is to require that there is always a top-level annotation
on the receiver for explicitness, and to require writing a dummy @Receiver
annotation when no other top-level annotation is present:
public @PolyNull Object[] toArray() @Receiver ArrayList<@PolyNull E> { ... }
This makes it clearer that the receiver is present for the purposes of
annotation, but programmers are likely to be irritated to have to write a
noise element like "@Receiver".

(Naturally, with all these proposals, if the receiver has no annotations,
nothing would have to be written at the end of the parameter list.)

If you have a better or different proposal, I would be glad to hear it.

Thanks,

-Mike

Adam Warski

unread,
Dec 3, 2009, 11:41:44 AM12/3/09
to jsr308-...@googlegroups.com
I think that the previous proposal:
public @PolyNull Object[] toArray() <@PolyNull> { ... }
was clear enough. It follows the way normal receiver annotations are written.

As to the @Receiver annotation, it makes one annotation "special" and part of the grammar of the language (if I understand correctly). So I would not go this way.

Adam

Michael Ernst

unread,
Dec 5, 2009, 1:32:41 AM12/5/09
to jsr308-...@googlegroups.com, ad...@warski.org
> I think that the previous proposal:
> public @PolyNull Object[] toArray() <@PolyNull> { ... }
> was clear enough. It follows the way normal receiver annotations are written.

OK, thanks for your input. To permit easier comparison, here are examples
of the proposed syntaxes:

Proposal with explicit type names:

interface Collection<E> {
public @PolyNull Object[] toArray() Collection<@PolyNull E> { ... }
}
interface List<T> {
public int size() @Readonly List<@Readonly T> { ... }
}
class MyMap<T,U> {
public void requiresNonNullValues() MyMap<T, @NonNull U> { ... }
}

Proposal with no explicit type names:

interface Collection<E> {
public @PolyNull Object[] toArray() <@PolyNull> { ... }
}
interface List<T> {
public int size() @Readonly<@Readonly> { ... }
}
class MyMap<T,U> {
public void requiresNonNullValues() <,@NonNull> { ... }
}

-Mike
Reply all
Reply to author
Forward
0 new messages