[
https://issues.apache.org/jira/browse/GROOVY-12240?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18102952#comment-18102952
]
ASF GitHub Bot commented on GROOVY-12240:
-----------------------------------------
testlens-app[bot] commented on PR #2772:
URL: https://github.com/apache/groovy/pull/2772#issuecomment-5222369543
## ✅ All tests passed ✅
🏷️ Commit: 4d53a4e3dfce02e147815e7ffc14b4234d8f8d97
▶️ Tests: 108926 executed
⚪️ Checks: 31/31 completed
---
_Learn more about TestLens at [testlens.app](https://testlens.app)._
> Initialize argument-less enum constants with a direct constructor call
> ----------------------------------------------------------------------
>
> Key: GROOVY-12240
> URL: https://issues.apache.org/jira/browse/GROOVY-12240
> Project: Groovy
> Issue Type: Improvement
> Components: Compiler
> Affects Versions: 5.0.8
> Reporter: Scott Murphy Heiberg
> Priority: Minor
>
> {{EnumVisitor}} creates every enum constant through a synthetic helper:
> {code:groovy}
> def $INIT(Object[] para) {
> return this(*para)
> }
> {code}
> {{this(*para)}} is a spread constructor call, so
> {{InvocationWriter.makeDirectConstructorCall}} refuses it — it bails on
> {{SpreadExpression}}, and again on {{!controller.isConstructor()}} — and the
> body compiles to {{ScriptBytecodeAdapter.despreadList}} plus
> {{selectConstructorAndTransformArguments}}. The meta class then picks the
> constructor at run time by reflecting over {{getDeclaredConstructors()}}. The
> static initializer reaches {{$INIT}} itself through a dynamic call site.
> For {{enum Colors { RED, GREEN, BLUE }}} that is the entire constant-creation
> path, even though the only arguments are the compiler-supplied name and
> ordinal, both known at compile time.
> Where reflection over the enum is not available, the class cannot initialize
> at all. In a GraalVM native image built without reachability metadata for the
> enum, {{getDeclaredConstructors()}} returns nothing and class initialization
> throws:
> {noformat}
> groovy.lang.GroovyRuntimeException: Could not find matching constructor for:
> com.example.MyEnum(String, Integer)
> {noformat}
> (note the boxed {{Integer}} — the ordinal has been through {{Object[]}}).
> This kills the application in a static initializer before any user code runs.
> {{@CompileStatic}} does not help. Groovy already compiles the *call site*
> statically (StaticTypeCheckingVisitor, GROOVY-10845); it is {{$INIT}}'s own
> body that is necessarily dynamic.
> h3. Proposal
> When every constant of an enum is a plain identifier, the arguments are
> provably {{[name, ordinal]}}, and the static initializer can call the enum's
> {{(String, int)}} constructor directly:
> {noformat}
> static {}; static {};
> 0: ldc // class Colors 0: new // class Colors
> 2: ldc // String RED 3: dup
> 4: iconst_0 4: ldc // String RED
> 5: invokestatic Integer.valueOf 6: iconst_0
> 8: invokedynamic invoke:(Class;String; 7: invokespecial
> "<init>":(Ljava/lang/String;I)V
> Integer;)Object; 10: putstatic Field
> RED:LColors;
> 13: invokedynamic cast:(Object;)LColors;
> 18: putstatic Field RED:LColors;
> {noformat}
> The same shape javac emits for a Java enum: 21 bytes and two invokedynamic
> call sites per constant become 13 bytes and none.
> Anything else — constants with arguments, named-argument form, anonymous
> constant bodies, or a mixture — keeps the existing {{$INIT}} path, as does
> any enum lacking a {{(String, int)}} constructor (checked at bytecode
> generation, after {{Verifier}} has run). {{$INIT}} itself is unchanged and
> still generated for every enum.
> h3. Scope, stated honestly
> This is a *compile-time* change. It only helps code compiled by a Groovy that
> carries the fix; bytecode already compiled by an earlier Groovy keeps its
> {{$INIT}} path whichever Groovy runs it. Confirmed by building a GraalVM
> native image of an application against a patched Groovy: the framework's own
> enums, compiled by an earlier Groovy, still failed with {{Could not find
> matching constructor}} until reachability metadata was restored.
> Enums whose constants take arguments ({{RED(255, 0, 0)}}) are not addressed
> and still require reachability metadata in a native image. Fixing those would
> mean relaxing {{InvocationWriter.makeDirectConstructorCall}} to work outside
> a constructor, which is a much wider change.
> Related to GROOVY-12234.
> I have a patch with tests ({{./gradlew :test}} passes in full: 16,548 tests,
> 0 failures) and will open a pull request against this issue.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)