jamesfredley commented on PR #15557: URL: https://github.com/apache/grails-core/pull/15557#issuecomment-4819691235
### Deep-dive: the `withDelegate` trait-static problem is GROOVY-12106, and it is still broken on `5.0.7-SNAPSHOT` I dug into why the GraphQL sub-traits cannot call the inherited `ExecutesClosures.withDelegate` static, since it is the one thing keeping the inline-duplication workaround in this PR. **Standalone reproducer:** https://github.com/jamesfredley/groovy-12106-repro (pure Groovy + Gradle, `./gradlew compileGroovy` fails on `5.0.7-SNAPSHOT`). #### Root cause Under `@CompileStatic`, when a child trait `extends` a parent trait and calls an inherited `static` helper, STC **misroutes** the call to the *child* trait's helper with a synthetic `$self`: ``` Cannot find matching method Arguable$Trait$Helper#withDelegate(java.lang.Class, groovy.lang.Closure, SimpleArgument) ``` The decisive trigger (found by bisection): **an argument whose static type is a proper subtype of the declared parameter type.** With `withDelegate(Closure, Object)`, calling it with a `CustomArgument`/`Field` (subtypes of `Object`) fails; calling it with an exact `Object` resolves fine. `@DelegatesTo`, a stateful trait field, and the presence of an implementer were all ruled out as necessary - only the subtype argument is required to reproduce the minimal case. This is exactly why **[GROOVY-12106](https://issues.apache.org/jira/browse/GROOVY-12106)** (which I filed) was closed **Resolved / Cannot Reproduce**: a naive minimal repro passes exact-typed arguments and compiles. The subtype case still fails on the current `GROOVY_5_0_X` tip - the repo above demonstrates it and I think the issue should be reopened with it. #### What does NOT fix it - `@groovy.transform.Virtual` (the replacement for the removed `@Anchored`): only restores per-implementer override dispatch for same-trait / implementing-class calls; it does not make a child trait resolve an inherited parent-trait static. Adding it does not change the failure. - Casting the argument to the exact parameter type (`withDelegate(closure, (Object) argument)`) fixes the *minimal* case, but in the full `grails-data-graphql-core` module it is **still not sufficient** (the real traits then fail with `Arguable#withDelegate(Closure, Object)` not found). So a cast is not a usable workaround for this PR. #### Conclusion for this PR The inline-duplication workaround already on this branch stays as the only reliable option until the Groovy STC fix lands. Once GROOVY-12106 is genuinely fixed in a `5.0.7-SNAPSHOT` build, the inlined blocks in `Arguable` / `ComplexTyped` can be deleted and replaced with a plain `withDelegate(closure, argument)` call. I left `// GROOVY-12106` markers on the inlined blocks so they are easy to find and remove later. #### Also fixed: the related `Validateable.defaultNullable()` CI failure The same finalized Groovy 5 trait-static model broke the *other* direction. After the `5.0.7-SNAPSHOT` switch, `ValidateableTraitSpec` had 2 failures (constraints nullable-by-default when overridden; overridden-`defaultNullable` properties not accessed during validation). Root cause: `Validateable`'s trait body calls `this.defaultNullable()`, and under the new **declarer-bound** default a plain trait static returns the trait's own `false` instead of an implementing class's override. Fix: annotate `Validateable.defaultNullable()` with `@groovy.transform.Virtual` (the matrix-documented "Grails `Validateable.defaultNullable`" use case) so the override is seen by trait-body calls. `:grails-validation:test` + `:grails-validation:codeStyle` now pass. External callers are unaffected (reflective static invocation / compile-time boolean). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
