[type-annos-observers] Fw: Constraining type annotations to occur just before type
Srikanth S Adayapalam
srikanth_sankaran at in.ibm.com
Wed Apr 3 22:11:14 PDT 2013
More comments from Eclipse JDT team...
Srikanth.
----- Forwarded by Srikanth S Adayapalam/India/IBM on 04/04/2013 10:40 AM
-----
From: Markus Keller/Zurich/IBM at IBMCH
To: Srikanth S Adayapalam/India/IBM at IBMIN@IBMDE,
Date: 04/03/2013 08:32 PM
Subject: Re: Fw: Constraining type annotations to occur just before type
> I reiterate that compile-time errors are used _only_ when the program's
> implied behavior would cause a run-time error.
Not really. There are e.g. compile errors if an annotation type cannot be
resolved, if an @Target annotation is wrongly placed on a non-annotation
type, or if an @Override annotation doesn't find a super method:
@Target(ElementType.METHOD)
public class Overriding {
@Override
public void bummer() { }
}
So the JLS can just as well demand that the compiler verifies that the
TYPE_USE annotations are at the right position.
> There is some confusion about what happens when an annotation type has
> TYPE_USE added as a target. No previous code becomes illegal.
It depends on the semantics of the annotation processor. Since JSR 308
specifies the class file format, it also partially specifies the semantics
of TYPE_USE annotations. Not the semantics of an annotation itself, but its
attachment point in the language model. In "@NonNull String[] s3", the
compilation depends on the annotation's @Target meta-annotation. If it's a
TYPE_USE annotation, it is now compiled as a Runtime
[In]VisibleTypeAnnotations. In this example, it's no longer an annotation
on the whole variable, but an annotation on the "String" type fragment of
the variable.
Adding TYPE_USE to an existing annotation may be superficially compatible
(on a syntactical level), but in practice, it's _always_ a breaking change,
since the TYPE_USE annotation is compiled into different attributes than
annotations with other ElementTypes, and since it sometimes targets a
different language element. Adding TYPE_USE to an existing annotation is
not a source-compatible change if you assume that the annotation has any
semantics (which is safe to assume, otherwise the annotation wouldn't
exist). And since we already have a source-incompatible change, it's not a
big deal if there's an additional restriction on the position of these
annotations.
> public static final @Foo @Bar String s;
To generate correct class files, the compiler must know whether the
annotations are TYPE_USE kinds or not. A purely syntactical parser indeed
can't tell, but as soon as types are resolved, the information is
available.
Markus
Alex Buckley <alex.buckley at oracle.com> wrote:
> I reiterate that compile-time errors are used _only_ when the program's
> implied behavior would cause a run-time error. Type annotations cannot
> cause that, so there is simply no case for a compile-time error about
> type annotations "in the wrong place".
>
> There is some confusion about what happens when an annotation type has
> TYPE_USE added as a target. No previous code becomes illegal. And
> forcing users to make a pass over their source is _never_ a feature of a
> programming language.
>
> I would add that even if type annotations were required to go at the end
> of the modifier list, it is still possible to write:
>
> public static final @Foo @Bar String s;
>
> Is @Foo a declaration annotation or a type annotation? If it's a poorly
> placed declaration annotation, then is @Bar the same, or a type
> annotation? You can't tell. It's up to the IDE to help out, not the
> compiler.
>
> Alex
>
> On 4/2/2013 1:02 AM, Srikanth S Adayapalam wrote:
> > [I am sorry I was away from my mail for a few days and couldn't
> > forward this feedback from Markus Keller of the Eclipse JDT team
> > earlier - Srikanth]
> >
> > ----------------8<------------
> >
> >> However, we cannot say that decl. annotations must come before
> >> traditional modifiers (private/public/static/final etc) because it has
> >> been legal since Java SE 5.0 to mix them up. The only rule which could
> >> possibly be added is "type annotations are not modifiers, and occur
> >> after all modifiers (which include declaration annotations)".
> >
> > I agree we can't fix the Java 5 mix-up. The proposed rule sounds good.
> >
> >
> >> I personally remain to be convinced that this rule is necessary.
> >
> > Allowing the TYPE_USE annotations not right in front of the variable or
> > return type is even more absurd if the type is an array or qualified
type:
> >
> > // Allowed (should be disallowed):
> > @NonNull final String s2 = new @NonNull String();
> >
> > // The @NonNull annotates "String", not the whole return type "String
[]":
> > @NonNull final String[] s3 = new @NonNull String[] { };
> >
> > // Not allowed (annotation on package "java"):
> > @NonNull final java.lang.String s4 = new @NonNull String();
> >
> > // What the user meant:
> > final java.lang. at NonNull String s5 = new @NonNull String();
> >
> >
> > I don't see any practical value in allowing TYPE_USE annotations to
show up
> > in front of other modifiers, but there's a clear reduction of confusion
if
> > they are only allowed at the end of the modifiers list.
> >
> > The compiler currently doesn't care much about the position of the
> > annotations because it only marginally processes the annotations (for
code
> > generation). On the other hand, every tool that processes annotations
is
> > also affected by the torn-apart type references, since the AST becomes
> > irregular.
> >
> > For refactoring tools, fetching the information from everywhere is a
mess,
> > and trivial rewrite operations like qualifying a type reference
(compare s2
> > with s4) need much more logic than necessary. For users who have to
read or
> > manually refactor such code, it's an even bigger mess.
> >
> > Since "conventions" in the JLS are not binding, they are not a big help
in
> > practice. Conventions are fine to help users avoid bugs from earlier
> > versions of the spec. But a new spec should not contain new conventions
if
> > it's trivial to just set a standard and avoid digressions.
> >
> > Let's list the arguments:
> >
> > Pro rule:
> > * Easier to understand for everybody
> > * Easier to process by tools and humans that refactor code
> > * If necessary, rule can be relaxed later; but it cannot be added later
> >
> > Contra rule:
> > * Source code incompatibility with pre-Java-8 hacks that use
> > declaration annotations to stand for type annotations.
> > => When an annotation becomes a TYPE_USE annotation, existing code
needs
> > to be massaged anyway. As the examples above show, the pre-Java-8 hacks
are
> > incompatible with Java 8 anyway. I'd even declare it a feature that
users
> > are forced to make a pass over their source in that case.
> > * Rule cannot be implemented by the parser since the grammar is
ambiguous.
> > The grammar cannot be fixed, since the parser cannot distinguish
TYPE_USE
> > from other annotations in these cases (the parser did not resolve the
> > @Target yet). The rule needs to be enforced at a later compilation
step.
> > * Rule needs to be implemented
> >
>
More information about the type-annotations-spec-observers
mailing list