Extending 15.28 to include toString() on an enum constant

Daniel Trebbien dtrebbien at gmail.com
Tue Jul 10 18:47:09 UTC 2018

On Mon, Jul 9, 2018 at 8:55 AM, Brian Goetz <brian.goetz at oracle.com> wrote:

> That said, there are some other operations that are far more deserving of
> better compile-time treatment.  In the context of raw string literals, we
> expect the `align()` call to be common; given that `align()` is pure,
> evaluating it at compile time rather than run time will be a big win.  You
> should expect to see this sort of thing coming out of JEP 303.  (Though I
> doubt it would go as far as `toString()` on enums, because at compile time,
> we cannot prove that _at run time_ `toString()` would not have been
> overridden.  Constant-folding of static methods is far less problematic
> than for virtual methods.)
> You raised a second case: constants in annotations.  This is very
> different in character from the first case.  The first case is a pure
> quest-for-performance; hoping that the compile/runtime can optimize
> something better.  The second is looking for language changes to make
> annotations more expressive; extending the notion of "constant expression"
> so more expressions can be used as annotation parameters.  We've actually
> thought about this quite a bit in the context of JEP 303.
> My conclusion is: this would be a bad idea.  It's great if the compiler
> can opportunistically spot opportunities to eliminate computation, but
> tying the semantics of a high-level language construct to this is pretty
> dangerous.  It means that in order to correctly reason about what can go in
> an annotation, every developer must be able to correctly reason about all
> the optimizations a compiler might do -- which is clearly a recipe for
> frustration and confusion.
> Additionally, I thing the resulting language is not one we'll want to
> program in.  When you pull this string to the end, you will end up with
> complex mini-programs as parameters to annotations.  But annotations are
> for metadata, not carriers for mini-programs.
> (We also confronted this from another angle; it has recently become
> practical to allow putting (non-bound) method references in annotations,
> which is a reasonable fit for the role of annotations.  But the obvious
> next question is: what about lambdas?  And while the machinery is the same,
> this is almost certainly over the line -- do we really want annotations
> stuffed full with little mini-method bodies (or, not so mini)?)

That's a good point about the toString() implementation changing between
compilations.  If a class SomeController is compiled against an AppAuthority
enum whose toString() implementation returns "something", and then the enum
is recompiled with a different toString() implementation that returns
"something_else", then the first compilation of SomeController is
outdated.  In such a scenario, it would be useful to have some sort of
runtime error diagnostic, but this, I think, would be the start of a One
Definition Rule in Java which probably isn't a great idea.

Could JEP 303 cover Enum#name()
since it's non-overridable?  Maybe name() could then be used within
constant expressions.

One difficulty with allowing name() to be used in constant expressions is
providing a diagnostic if the enum is recompiled to remove an enum constant
that was inlined into a constant expression in some other compilation
unit.  By way of example, suppose we have AdminController as follows:

@Secured({ AppAuthority.ROLE_ADMINISTRATOR.name() })
public class AdminController {

.. and then AppAuthority is modified to remove the ROLE_ADMINISTRATOR enum
constant.  In such a scenario, I think that there should be some sort of
LinkageError thrown when the AdminController class is loaded by the JVM.

More information about the amber-spec-observers mailing list