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()
<https://docs.oracle.com/javase/10/docs/api/java/lang/Enum.html#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:
@Controller
@RequestMapping("/admin")
@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