spec clarification: wildcard array element signature

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Oct 24 21:35:37 UTC 2016

On 24/10/16 19:28, Alex Buckley wrote:
> First, I don't know why javac is denoting the type of i using A rather 
> than B, both in the field descriptor and in the Signature attribute. 
> The field descriptor is specified in JLS8 13.1 as containing "a 
> symbolic reference to the erasure of the type of the field". Plainly 
> this is LB$I, and Signature would follow suit.
I think this is coming from this rule (13.1):

"The binary name of a member type (§8.5, §9.5) consists of the binary 
name of its immediately enclosing type, followed by $, followed by the 
simple name of the member."

The rule speaks about 'enclosing type' hence A being used instead of B I 
believe. But that counts for the descriptor.

As for the contents of the signature attributes, my feeling is that the 
signature attribute attempts to 'augment' the information that's 
available in the descriptor, not completely replace it. I think having, 
say, Field.getType return A, but Field.getGenericType return 
B<something> would be a little weird, I believe. Other compilers such as 
ecj seem to be doing the exact same thing in this respect.

> Second, there is nothing in JLS8 8.1.2 to deny B<?>'s supertype being 
> A<?[]>, so to speak. But it was never envisaged in JVMS8 that 
> there would be a type parameterized by "array of wildcards". This may 
> be due to the trickiness of Signature having multiple roles: it 
> reifies generic type information like B<Y> (where array types are not 
> permitted as type parameters) in addition to parameterized type 
> information like A<Y[]> (where array types are permitted as type 
> arguments).
Right - this is not explicitly disallowed - but it seems in contrast to 
the rules for computing the supertype of a generic class: the supertype 
of B<?> is not A<?[]> but A<#CAP[]>, where #CAP <: Object. I believe 
keeping wildcards open in the bytecode (which is something ecj does too) 
might result in unsoundness? Presence of arrays here is largely 
irrelevant - if the supertype was just A<Y> wouldn't still be 
problematic to use A<?> as the field type?

At the same time, there's no representation at the bytecode level for 
captured variables, so there's not much that can be done in that space.
> Third, on JDK 9b140, javac crashes if the declaration of i uses a 
> bounded wildcard for B's type argument -- say B<? extends Number>.I
> java.lang.ClassCastException:
> com.sun.tools.javac.code.Type$TypeMapping$3 (in module: jdk.compiler)
> cannot be cast to
> com.sun.tools.javac.code.Type$WildcardType (in module: jdk.compiler)
> at 
> com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.validateAnnotatedType(jdk.compiler at 9-ea/Attr.java:4804)
This is a bug - I've also been able to reproduce on JDK 8.

Regarding the other issue about wildcards being replaced in supertypes, 
I think there are two options - none of which is particularly appealing:

* fix javac (and other compilers) so that the signature attribute only 
speaks about types in the source code, w/o attempting to do any 
membership computation - this should ensure that non-denotable types 
should not crop up in the process - unfortunately, doing so will change 
the signature attribute of real code out there - and the compatibility 
impact potentially large (the difference will be visible in core 

* keep javac as is - live with 'weird' signatures and plug resulting 
soundness issues (esp. around separate compilation) ?

> Looking for others to comment.
> Alex
> On 10/22/2016 8:15 PM, Liam Miller-Cushon wrote:
>> When javac compiles the following program, it writes field i's signature
>> as "LA<[*>.I;".
>> I don't think the grammar in JVMS allows for the element type of
>> an array to be a wildcard. Is that a spec bug?
>> class A<X> { class I {} }
>> class Test {
>>    class B<Y> extends A<Y[]> {}
>>    B<?>.I i;
>> }

More information about the compiler-dev mailing list