type_path of constructors for inner classes

Alex Buckley alex.buckley at oracle.com
Fri Oct 11 15:40:30 PDT 2013

On 10/11/2013 12:30 PM, Werner Dietl wrote:
> The JSR 308 spec unfortunately doesn't make it clear what behavior is
> required, so maybe it's best to raise the issue to the EG.

When javac finds an annotation on the simple name of a nested type, it 
appears to first expand the simple name to a qualified name, and then 
describe the annotation with a target_path item. So, the @Annot(99) 
annotation in:

class Test {
   class Inner {}
   void m(@Annot(99) Inner i) {}

is deemed to really be "Test. at Annot(99) Inner". A one-entry type_path 
structure is emitted as the target_path item, and javap renders it as 

That's all fine. The draft JLS/JVMS text for 308 - which I now regard as 
"the spec" - doesn't say that simple names must be expanded because 
that's the kind of thing compilers usually do automatically.

In any case, I would have expected javac to treat the type of the newly 
constructed object as Test.Inner too, and place @Annot(0) in the same 
nested location. The type of the newly constructed object is just as 
much Test.Inner as with the i parameter in my m method above.

> A constructor doesn't have a return type in the same sense as a method.
> One cannot have annotations on type arguments or outer types on a
> constructor result.
> The spec says:
> "Outer class annotations for a constructor result must be identical to
> those on the receiver, so they can be inferred from the annotations on
> the receiver."
> So not having the location seems OK, because there is no possible ambiguity.

I have not transferred this "must be identical" clause to the spec 
because I don't know what it means. First, in a nested class 
declaration, you can't write the type of the constructor result, so you 
can't write outer class annotations. Second, when I see "must" in 
normative text, I look for the error to be given if the clause is 
violated, but no error is mandated here.

Please supply two declarations, one which you think should give an error 
and one which should not.

> The JavaDoc for javax.lang.model.type.ExecutableType.getReturnType()
> currently says:
>       * Returns the return type of this executable.
>       * Returns a {@link NoType} with kind {@link TypeKind#VOID VOID}
>       * if this executable is not a method, or is a method that does not
>       * return a value."
> So I would assume that the result for an annotated constructor would be
> an annotated NoType, containing only the annotations on the result,
> without any locations.
> A better alternative might be that the result type of the constructor
> uses the actual return type instead of NoType and performs the inference
> of the annotations from the receiver type.
> It would then probably be easier and more consistent if the result
> annotations contained the location information.

Our thinking is that a ctor does not have a return type, so 
getReturnType() for a ctor's Executable really must give a NoType. 
Annotations on the ctor with target_type=0x14 ("return type of method, 
or type of newly constructed object") will be exposed on the NoType. 
It's not worth complicating with receiver annotations.


> On 10/02/2013 03:32 PM, Joel Borggrén-Franck wrote:
>> Hi Werner,
>> When looking at the byte code for this class:
>>    3 public class Test {
>>    4     class Inner {
>>    5         @Annot(0) public Inner(@Annot(1) Test Test.this) {}
>>    6
>>    7         public @Annot(5) Inner foo(@Annot(55) Test.Inner Test.Inner.this) { return new Inner(); }
>>    8     }
>>    9 }
>>   10
>>   11 @Retention(RetentionPolicy.RUNTIME)
>>   12 @Target(ElementType.TYPE_USE)
>>   13 @interface Annot {
>>   14     int value();
>>   15 }
>> javap output this for the method foo();
>>    public Test$Inner foo();
>>      descriptor: ()LTest$Inner;
>> ...
>>      RuntimeVisibleTypeAnnotations:
>>        0: #13(#14=I#21): METHOD_RETURN, location=[INNER_TYPE]
>>        1: #13(#14=I#22): METHOD_RECEIVER
>> and this for the ctor:
>>   public Test$Inner(Test);
>>      descriptor: (LTest;)V
>>>>      RuntimeVisibleTypeAnnotations:
>>        0: #13(#14=I#15): METHOD_RETURN
>>                                                                          ^^^^^^ no location here ...
>>        1: #13(#14=I#16): METHOD_RECEIVER
>> I think it is a bug that the ctor METHOD_RETURN lacks the location/encoded type_path.
>> What do you think?
>> cheers
>> /Joel

More information about the type-annotations-dev mailing list