Fix Java enum forwarders to pull from companion on initialization #24361
+58
−3
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #12637
Previously, Java enum forwarders were initialized to null when the companion's static initializer was triggered before the Java enum forwarder class's static initializer.
For example, when
enum Testme extends java.lang.Enum[Testme]is accessed from Scala (which accessesTestme$.Hello):Testme$.<clinit>is triggeredTestme$.new(...)Testme$$anon$1(which representsHello), a subtype ofTestmeTestme.<clinit>is triggeredTestme.<clinit>tries to initialize itsTestme.Hellofield by pulling fromTestme$.HelloSee: #12637 (comment)
full javap result is available here: https://github.com/tanishiking/kitchensink/tree/main/scala3/12637
This commit fixes the initialization problem by having the companion object's static initializer push enum values to the forwarders after it finishes initializing the enum value fields.
When the companion is accessed first:
<clinit>runs and creates enum values<clinit>is triggered<clinit>pushes final values to forwarders at the endWhen the forwarder is accessed first:
<clinit>tries to initialize the forwarder viagetstaticfrom the companion<clinit>first<clinit>pushes values to the forwardersputstaticcompletes (resulting in double assignment, but with the correct value)Drawbacks:
Now it's possible to update the static forwarder like
If making the Java enum forwarder non-final isn't acceptable, other option would be generating a proxy method like for Scala.js, but Java will need to call
Testme.Hello(), instead ofTestme.Hello.