2 questions about enums and the closed/withdrawn JEP 301

David Alayachew davidalayachew at gmail.com
Wed Mar 29 18:02:03 UTC 2023


Hello Archie,

Thank you for your response!

Also, ty again for all the help on the compiler-dev issue with the .class
filenames with similar case! I appreciate all the help you all gave.

> Can I say "me too"?? :) I've always wanted
> to be able to declare an instance method
> whose return type is the same type as the
> instance. In fluent API's, it would
> eliminate a bunch of override methods
> that are only there to narrow the return
> type.

Oh cool, I never thought of it this way. Yes, that would make writing
utilities way easier, and fluent api's like you said.

> On the enum question...
>
> When I was programming Java before
> there were enums, I would homebrew my
> own enums.
>
> When enums were invented, I thought
> "Great! The compiler will do all that stuff
> for me". I could clearly see that it was
> just a matter of the compiler
> automatically doing a transformation I
> was already doing manually.
>
> Today when I want a generic enum type, I
> go back to homebrewing my own enums
> just like before, with generic parameter(s)
> as needed.

Yeah, enums feel really intuitive with respect to what originally you were
doing vs what the compiler enables for you. It feels very much like records
do now. That's actually part of the reason that this lack of functionality
with generics on the class level hurts so much for enums. It forces me to
come crashing back down to normal classes. It's like going onto local roads
doing 35 when I was cruising on the highway doing 70.

> So from a practical perspective most
> developers probably don't understand
> why this shouldn't be "easy". If a
> developer can do it manually, the
> compiler should be able to do it
> automatically.

I've received so many great answers already, but none of them have
attempted to answer the second half of the question - why was this done in
the first place? I hope someone will be able to answer that eventually.
Maybe it was a mistake to bundle them together in a single post.

Maybe the original designer of that feature has since left the development
team and it is currently unknown?

> Also, it's kind of perplexing that the
> show-stopping barrier here is not with the
> Enum type itself, but with the
> EnumSet/EnumMap utility classes.

So, thanks to Tesla, Brian, and everyone else, I now feel confident enough
to correct this and explain what the actual intent was. Thanks again
everyone!

Originally, yes, the concern was about a bunch of errors that popped up on
EnumSet and EnumMap when adding generics to the enum. When digging into
that, they realized that f bounded types in general don't play well with
any collection, which they later explained with the term heterogeneous
types. All this means is that, at the time, the team couldn't see a clear
way for the type system to represent a Collection of a bunch of E's, each
with their own, potentially different, type parameter. To my understanding,
saying I have a Collection of a bunch of E's whose type parameter is ?
(unknown) is basically saying that every one of those E's has a type
parameter that is the exact same type, even if it is only the parent (like
java.lang.Object).

This means that you would run into a very similar issue if you tried to
have a Collection of any type T, where instance of that type T has its own,
separate value for its type parameter.

Maurizio closed the original post by saying they were exploring ways to
improve the type system so that they actually COULD model this
functionality. However, until that happens, or the blocker is removed,
Maurizio suggested shelving until then.

The second post, however, took things in a different direction. Rather than
considering raw types (and the errors that came with it) to be failure
states, the team took a closer look at the rules and saw that the rules and
errors thrown for generics were actually lacking in a lot places, leading
to false positives and negatives. Seeing that, they then thought about
trying to outright change/add rules to better represent what is and is not
safe to do in generics.

In short, the second post offered up the idea of saying that a more precise
typing rule could be added that would allow the supertype to choose not to
depend on its type parameter if it is not actually going to use it.

This was a very complex idea for me to wrap my head around, but thanks to
these past several comments I got it now.

What that idea means is that - if I have a Collection of E's, each with
their own type parameter, then I may not need to know the type parameter of
any of the elements of my collection, at least not at that moment. So, if I
have an enum where value1 has a type parameter of String, and value2 has a
type parameter of Integer, and I stick both of these values in an
Collection, I know that I have no way of knowing the type parameter of the
value that I passed in until I can identify which value it is (like through
a switch statement for an example). As a result, I actually don't care
about the type parameter until I can single this out to the individual
type. AND THEREFORE, if my error is complaining that about the type
parameter of my bunch of E's, this new type rule would allow me to say "I
give up the ability to know what the type parameter of the value is until I
hammer down which enum value this is". Because of that, I have placed a
constraint on myself that prevents me from hurting myself through a bad
generic method call, and therefore, I don't need that restriction in this
case. Hence, the sharper type checking rules allowing us to learn when and
where this situation applies so that we can lift that constraint off of the
programmer.

Now, this is not a clean break, it allows some bugs that previously not
possible. However, with respect to the issue of trying to represent a
Collection of a generic enum, it removes the biggest issues, and the other
obstacles are doable. Just the big takeaway was that, thanks to the new
typing rule, we can use a raw type not only as an on-ramp for old code
upgrading to generics, but go further and claim that whatever E this
Collection is a Collection of can all be assumed to be heterogeneous, which
allows us to say, we won't use their type parameters, so we don't need to
check them at this moment.

Maurizio closes it off by saying that the problem is no longer about trying
to make enums be generic wile playing well with EnumMap and EnumSet. That
problem has been thoroughly dealt with and is no longer a blocker.

The real problem is - is this really a desirable way of doing this?
Implementing the typing rules takes effort, and now, these raw types open
up room for bugs in generics that weren't there before. Is giving enums
generics (or more properly, allowing a generic data structure the ability
to have heterogeneous E) worth the new problems that will be opened up in
the generics system?

In short, the answer ended up being no. They felt like the amount of
complexity and the new issues plus level of effort to implement this. So,
JEP withdrawn forthe time being.

I could be wildly wrong here, but at least it feels like it makes sense lol.

> Regarding that problem, would it work to
> just add "workaround" methods like this?
>
>         public static <T extends Enum<T>>
>            EnumSet<T>
>            noneOfGeneric(Class<? extends T> klass)
>
> Even though klass has type Class<?
> extends T>, at compile time, you're not
> going to be able to specify any Class
> constant other than the top enum class,
> so no problem there, and at runtime, this
> method could do introspection to find the
> top enum class (if necessary; unlikely)
> and then use that.

I am not sure. To my understanding, this would likely fail for the same
reasons why noneOf failed. It's failing because it doesn't know how to
handle heterogeneous types in a generic data structure. In this case, your
enum is the heterogeneous type, and the EnumSet (or any collection) is the
generic data structure.

Thank you for your time and help!
David Alayachew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230329/ce80ecf4/attachment-0001.htm>


More information about the amber-dev mailing list