[enhanced-enums]: Enhanced enums failure with raw types?

B. Blaser bsrbnd at gmail.com
Mon Sep 11 11:38:32 UTC 2017


Hi,

On 11 September 2017 at 10:35, Maurizio Cimadamore
<maurizio.cimadamore at oracle.com> wrote:
> Thanks B.
> unfortunately, the enhanced enum feature is not gonna make it, because of
> serious issues discovered during the exploration phase - see this email:
>
> http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html
>
> That said, I can't find 'raw type in an enhanced enum' in your example - is
> this the right source? You mean 'F' - which is not raw - just
> unparameterized?

The problem is in "E" ("F" and "C" are working fine, they are just
here as comparison):

public class A {
    enum E<X> {
        INTEGER(Integer.class);
        E(Class<X> clazz) {}
    }
}

This simple example doesn't compile because the current version of
javac determines "E<X>" as type for "INTEGER" and is then expecting
"Class<X>" as argument to the constructor which is incompatible with
"Class<Integer>" (INTEGER<Integer> would work fine).

So, I think the type of INTEGER (in our example) should be "E", the
erasure of "E<X>", and the expected argument would be "Class" which is
compatible with "Class<Integer>" (but producing an unchecked warning).

We could simulate this with classes, as follows:

public class A {
    static class C<X> {
        C INTEGER = new C(Integer.class);
        C(Class<X> clazz) {}
    }
}

I think this is only a small compiler bug (see the patch below), not a
problem of specification.
The fix simply ensures that "INTEGER" (without type argument in the
parameterized enum "E<X>") will have type "E" and not "E<X>" which
wouldn't make any sense at my opinion.

Note that the output of "javac -Xlint:unchecked A.java" I gave
yesterday is what I would expect (and it's produced with the fix I
suggested).
The actual version simply fails to compile this example ending with an
error as explained above.

I hope this is clearer...
What do you think?

Cheers,
Bernard

> Cheers
> Maurizio
>
>
>
> On 10/09/17 18:20, B. Blaser wrote:
>>
>> Vicente, Maurizio, All,
>>
>> Consider the following example involving a raw type in an enhanced enum:
>>
>> public class A {
>>      enum E<X> {
>>          INTEGER(Integer.class), FLOAT<Float>(Float.class);
>>          E(Class<X> clazz) {}
>>      }
>>
>>      enum F {
>>          INTEGER(Integer.class);
>>          F(Class<?> clazz) {}
>>      }
>>
>>      static class C<X> {
>>          C INTEGER = new C(Integer.class), FLOAT = new
>> C<Float>(Float.class);
>>          C(Class<X> clazz) {}
>>      }
>> }
>>
>> Javac fails to compile the latter but I'd be more expecting an
>> unchecked warning instead, as for classes:
>>
>> $ javac -Xlint:unchecked A.java
>> A.java:3: warning: [unchecked] unchecked call to E(Class<X>) as a
>> member of the raw type E
>>          INTEGER(Integer.class), FLOAT<Float>(Float.class);
>>                 ^
>>    where X is a type-variable:
>>      X extends Object declared in enum E
>> A.java:13: warning: [unchecked] unchecked call to C(Class<X>) as a
>> member of the raw type C
>>          C INTEGER = new C(Integer.class), FLOAT = new
>> C<Float>(Float.class);
>>                      ^
>>    where X is a type-variable:
>>      X extends Object declared in class C
>> 2 warnings
>>
>> I've provided a simple fix here under (repo.: amber, branch:
>> enhanced-enums, rev.: 7a22956a0562).
>>
>> Any comment is welcome,
>> Bernard
>>
>> diff -r 7a22956a0562
>> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
>> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
>>     Fri Sep 08 00:00:41 2017 +0200
>> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
>>     Sun Sep 10 16:23:02 2017 +0200
>> @@ -903,15 +903,19 @@
>>       }
>>
>>       Type attribExprAsEnumType(Env<AttrContext> env, JCExpression type) {
>> +        return attribExprAsEnumType(env, type, true);
>> +    }
>> +    Type attribExprAsEnumType(Env<AttrContext> env, JCExpression
>> type, boolean erase) {
>>           if (type.hasTag(IDENT)) {
>>               JCIdent id = (JCIdent)type;
>>               Assert.check((env.enclClass.sym.flags() & ENUM) != 0);
>> -            id.type = env.info.scope.owner.enclClass().type;
>> +            Type t = env.info.scope.owner.enclClass().type;
>> +            id.type = t.isParameterized() && erase ? types.erasure(t): t;
>>               id.sym = env.info.scope.owner.enclClass();
>>               return id.type;
>>           } else {
>>               JCTypeApply ta = (JCTypeApply)type;
>> -            Type enumBaseType = attribExprAsEnumType(env, ta.clazz);
>> +            Type enumBaseType = attribExprAsEnumType(env, ta.clazz,
>> false);
>>               ResultInfo prevInfo = resultInfo;
>>               resultInfo = unknownTypeInfo;
>>               try {
>
>


More information about the amber-dev mailing list