jamesfredley commented on PR #15557:
URL: https://github.com/apache/grails-core/pull/15557#issuecomment-4833554145
### Correction + real root cause: GROOVY-12106 is in the snapshot, but its
fix is order-dependent and misses this case
My previous comment was wrong on one point and I want to correct the record
clearly.
**What I got wrong:** I claimed the consumed `5.0.7-SNAPSHOT` (build 18,
`5.0.7-20260628.011302-18`) *predated* the GROOVY-12106 fix. It does not. The
CI run that produced build 18 (`Generate SNAPSHOT distributions`, run
28307143921) was triggered by the fix commit `b46ebb25e7` itself (run window
`01:05:34Z → 01:14:08Z`; snapshot timestamp `01:13:02Z` sits inside it). **The
GROOVY-12106 fix is present in build 18.** Thanks for pushing on the timeline.
**The real reason the `Arguable` / `ComplexTyped` inline must stay:** the
GROOVY-12106 fix does not cover the Grails shape, because it is
**order-dependent**.
- The fix (`b7796c3f9b`, PR #2635) is entirely in
`TraitTypeCheckingExtension` - the STC layer. It does subtype-aware lookup over
the super-trait helper's declared statics, but only *after* the call has
already been rewritten into `…$Trait$Helper.withDelegate($static$self, closure,
arg)` form.
- That rewrite happens earlier, in
`TraitReceiverTransformer.findConcreteMethod`. If the super-trait's
`$Trait$Helper` has not been generated yet when the sub-trait body is
transformed, `findConcreteMethod` returns null and the call is left as a plain
`Arguable#withDelegate(Closure, Object)` - so the fixed STC branch (which keys
off `isClassType(argumentTypes[0])`, i.e. the synthetic `$static$self` Class
arg) is never entered.
- In this module the files sort `Arguable` / `ComplexTyped` **before**
`ExecutesClosures` alphabetically, so the sub-traits are transformed first and
hit exactly this gap. Groovy's own passing test
`Groovy12106.testGrailsHelperShapeWithDelegatesTo` declares the parent trait
first in a single script, so it never triggers the ordering.
**Proof** - minimal self-contained reproducer compiled against build 18 (and
against a local Groovy build from `b46ebb25e7`):
```groovy
import groovy.transform.CompileStatic
final class FieldA {}
@CompileStatic
trait ArguableA<T> extends ExecutesClosuresA { // sub-trait
declared FIRST
String describe(FieldA f) { withDelegate({ -> }, (Object) f); 'ok' }
}
@CompileStatic
trait ExecutesClosuresA {
static void withDelegate(@DelegatesTo(strategy = Closure.DELEGATE_ONLY)
Closure c, Object d) { if (c != null) c.call() }
}
class CA implements ArguableA<String> {}
```
- Sub-trait-first (above) → **fails**: `Cannot find matching method
ArguableA#withDelegate(groovy.lang.Closure, java.lang.Object)` - the exact
Grails error.
- Reverse the two trait declarations (super-trait first) → **compiles**.
This is essentially `Groovy12106.testGrailsHelperShapeWithDelegatesTo` with
only the declaration order reversed. It looks like a distinct upstream
transform-order defect, earlier than the 12106 STC fix - reminiscent of the
older [GROOVY-11743](https://issues.apache.org/jira/browse/GROOVY-11743) "super
trait may not be transformed when creating helper". Worth a follow-up ticket
for Paul with the reproducer above (the real fix would be in
`TraitReceiverTransformer.findConcreteMethod`: fall back to the super-trait's
declared statics when its helper is not yet generated, or order helper
generation before sub-trait body rewriting).
**Grails-side escape hatches tried and rejected:** plain
`withDelegate(closure, argument)`, `(Object)`-cast, `this.withDelegate(...)`,
and making `withDelegate` an instance method all fail - the instance +
`@DelegatesTo` form fails to bind (`Not enough arguments found for a
@DelegatesTo method call`), and `withDelegate` is used across ~8 GraphQL files,
so a signature change is invasive. So the inline stays.
The in-code comments and the PR description have been corrected to this root
cause in `12292b860b`. The inline can drop to the byte-identical `8.0.x`
`withDelegate(closure, (Object)…)` call once the upstream transform-order gap
is fixed.
Assisted-by: claude-code:claude-4.8-opus
--
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]