type_path of constructors for inner classes
Werner Dietl
wdietl at gmail.com
Fri Oct 11 16:22:50 PDT 2013
Alex, all,
when reading "type of the newly constructed object" it seems to me
like you're talking about an object creation - a "new" expression.
There is a "new Inner();", but there is no type annotation there. Are
you talking about line 7 or 5 in Joel's example?
If I change line 7 to
public @Annot(5) Inner foo(@Annot(55) Test.Inner Test.Inner.this)
{ return new @Annot(555) Inner(); }
And look at the generated bytecode, I see:
RuntimeVisibleTypeAnnotations:
0: #16(#17=I#23): NEW, offset=0, location=[INNER_TYPE]
RuntimeVisibleTypeAnnotations:
0: #16(#17=I#24): METHOD_RETURN, location=[INNER_TYPE]
1: #16(#17=I#25): METHOD_RECEIVER
That behavior seems correct to me.
If there is no type annotation in the "new" expression, there are no
type annotations in the bytecode; If there are type annotations on the
"new" expression, only those show up - with the correct location. This
is independent of what type annotations are on the constructor result.
Should constructor result annotations be considered for "new" expressions?
However, I think we were talking about the constructor result
annotations, that is, about line 5.
Do you consider the constructor name a simple type name?
In line 5:
@Annot(0) Inner(@Annot(1) Test Test.this) {}
It is not possible to make the outer type of the result explicit, that
is, one cannot write:
@Annot(666) Test. at Annot(0) Inner(@Annot(1) Test Test.this) {}
Therefore, @Annot(1) is the only possible annotation for outer type of
the constructor result.
In your last paragraph, you have:
> 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.
If the constructor result type is a NoType, wouldn't it be confusing
if it had a location in bytecode? To me the location INNER_TYPE would
only make sense if the result type were "@Anno(1) Test. @Anno(0)
Inner".
If we use NoType as the result type, I feel like the current behavior
of javac is correct.
Thoughts?
cu, WMD.
On Fri, Oct 11, 2013 at 6:40 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> 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
> "location=[INNER_TYPE]".
>
> 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.
>
> Alex
>
>
>> 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
>>>
>
--
http://www.google.com/profiles/wdietl
More information about the type-annotations-dev
mailing list