type_path of constructors for inner classes
Werner Dietl
wdietl at gmail.com
Fri Oct 11 17:13:52 PDT 2013
Are you saying the correct annotations for the constructor of Inner would be:
RuntimeVisibleTypeAnnotations:
0: #16(#17=I#19): METHOD_RETURN
1: #16(#17=I#18): METHOD_RETURN, location=[INNER_TYPE]
2: #16(#17=I#19): METHOD_RECEIVER
That is, the @Annot(1) from the receiver appears again on the return
and the @Annot(0) appears on the return, with a location.
Or should we avoid this duplication and only keep 1 and 2, that is the
two explicit annotations?
> I'm not talking about 'new' at all. I say "type of the newly constructed
> object" to indicate the type to which a TYPE_USE annotation in front of a
> ctor declaration applies. I got the phrase from page 3 of
> java-annotation-design.pdf:
I find this wording in the design document rather unclear. Will this
appear in the JLS like this?
> You're saying that the "true" type of the newly constructed object at line 5
> is:
>
> @Annot(1) Test . @Annot(0) Inner
>
> and I agree. So why aren't there two annotations for the METHOD_RETURN
> target of the ctor, one with a location clause? You'd expect _at least_ the
> @Annot(0) to be emitted with a location clause.
Expectations seem to be different and the JLS should be written in a
way to clarify this situation, imo.
cu, WMD.
On Fri, Oct 11, 2013 at 7:56 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> On 10/11/2013 4:22 PM, Werner Dietl wrote:
>>
>> 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?
>
>
> I'm not talking about 'new' at all. I say "type of the newly constructed
> object" to indicate the type to which a TYPE_USE annotation in front of a
> ctor declaration applies. I got the phrase from page 3 of
> java-annotation-design.pdf:
>
> "A type annotation is permitted in front of a constructor declaration, where
> declaration annotations are already permitted. In that location, a type
> annotation is treated as applying to the constructed object (which is
> different than the receiver, if any, of the constructor)."
>
>
>> 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.
>
>
> Yes. Note that @Annot(5) on the return type is really "Test.Inner
> @Annot(5)", hence there's a location clause, whereas @Annot(55) on the
> receiver parameter's type is truly on the Test of "Test.Inner", so there's
> no location clause.
>
>
>> 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?
>
>
> Yes. As a matter of interest, the only place that SimpleTypeName appears in
> the language grammar is ConstructorDeclarator.
>
>
>> 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.
>
>
> You're saying that the "true" type of the newly constructed object at line 5
> is:
>
> @Annot(1) Test . @Annot(0) Inner
>
> and I agree. So why aren't there two annotations for the METHOD_RETURN
> target of the ctor, one with a location clause? You'd expect _at least_ the
> @Annot(0) to be emitted with a location clause.
>
>
>> 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.
>
>
> I see what you mean, but we're really talking about different things:
>
> - A compiler can emit a "true" nested type (@Annot(1) Test . @Annot(0)
> Inner) as the type of a newly constructed object, and Core Reflection should
> be able to deal with it - j.l.r.Constructor inherits
> getAnnotatedReturnType() from j.l.r.Executable, so we made that method
> understand that a ctor may be annotated with the type of the constructed
> object.
>
> - In the Language Model API, we give a NoType for a ctor's "return type"
> because in the JLS, a constructor does not have a return type. All you can
> do with the NoType is get its TYPE_USE annotations, which I would hope is
> @Annot(0). You can't distinguish between Test and Inner, but that's not a
> big deal because you're getting the annotation which was written at the
> appropriate location in the source code. An alternative would be to give a
> DeclaredType, since it would expose the "enclosing type" Test as distinct
> from Inner, but that would not be consistent with the JLS.
>
> Alex
>
>
>> 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