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

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Sep 11 13:27:31 UTC 2017


Yep - it's a bug in the impl - in the sense that the members of a raw 
types are erased, meaning that the constructor of E, viewed as a member 
of a raw type is simply:

E(Class clazz)

So, your code should work (with warning).

That said, I don't think fixing this is a priority, (as anticipated) 
given the current status of the feature.

Maurizio


On 11/09/17 12:38, B. Blaser wrote:
> 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