[
https://issues.apache.org/jira/browse/GROOVY-12106?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18092081#comment-18092081
]
Paul King edited comment on GROOVY-12106 at 6/28/26 1:19 AM:
-------------------------------------------------------------
After GROOVY-12106 changes (the case-(b) fix) on **master**, **GROOVY_5_0_X**,
and the spec (**asf-site**), here's how the issue's behaviour table changes.
Three deltas: the (b) rows flip green on both lines; the GEP-22 column goes
from *Silent* to *Documented*; and the (a)/qualified row's 5.0.x gap
**persists** (12106 didn't include the master-only interface promotion).
Updated table:
|| Row || Form || Case || 4.0.32 || 5.0.6 || 5.0.7-SNAPSHOT (GROOVY_5_0_X) ||
6.0.0-SNAPSHOT (master) || GEP-22 v6 ||
| 16 | unqualified {{m(...)}} | (b) | (/) | (x) | (/) | (/) | *Documented* |
| 16b | {{this.m(...)}} | (b) | (/) | (x) | (/) | (/) | *Documented* |
| 16q | qualified {{Parent.m(...)}} | (a) | (x) ^1^ | (x) | (x) ^2^ | (/) |
*Documented* |
| - | {{Parent.super.m(...)}} | escape | (/) | (/) | (/) | (/) | *Documented* |
| - | unqualified, _exact_ {{Object}} arg | - | (/) | (/) | (/) | (/) |
*Documented* |
| D | plain class {{Child extends Parent}} | control | (/) | (/) | (/) | (/) |
_n/a_ |
^1^ Qualified on 4.0.32 _compiles_ but throws {{MissingMethodException}} at
runtime — it never fully worked there. All other cells are compile + runtime.
^2^ Qualified still fails on 5.0.x: GROOVY-12106 fixed the
unqualified/{{this.}} forms (case b), but the qualified form (case a) resolves
via the trait's _promoted interface static_, which requires GROOVY-12111 — that
is master-only and was **not** part of the 12106 backport.
h4. What the columns show
* *5.0.6* — the released, pre-fix 5.0.x baseline: case (b) and (a) both fail;
only {{super}}/exact/plain-class work.
* *5.0.x (+12106)* — the {{GROOVY_5_0_X}} tip after the backport: case (b) now
resolves (rows 16/16b flip (x) → (/)); (a) still fails pending a GROOVY-12111
backport.
* *6.0.0 (master)* — full feature set: (a) and (b) both resolve.
h4. What changed vs the previous table
* *Case (b) — rows 16 / 16b:* {{5.0.x (+12106)}} and master are now (/). 5.0.6
stays (x) (it predates the fix), making the regression-and-repair visible
across the row: 4.0.32 (/) → 5.0.6 (x) → 5.0.7-SNAPSHOT (/).
* *GEP-22 column:* was *Silent* for the (b) rows; GEP-22 now documents
inherited super-trait static resolution, so every trait row is *Documented*.
* *Case (a) — row 16q:* unchanged — (/) only on master; still (x) on every
5.0.x build (needs GROOVY-12111).
h4. Net for Grails using Groovy 5.0.x
The natural call forms (unqualified and {{this.}}) and the {{super}}/exact
forms all work on 5.0.x now. The only form still failing on 5.0.x is the
explicitly-qualified {{Parent.m(...)}}, which would require backporting
GROOVY-12111 as well.
was (Author: paulk):
After GROOVY-12106 changes (the case-(b) fix) on **master**, **GROOVY_5_0_X**,
and the spec (**asf-site**), here's how the issue's behaviour table changes.
Three deltas: the (b) rows flip green on both lines; the GEP-22 column goes
from *Silent* to *Documented*; and the (a)/qualified row's 5.0.x gap
**persists** (12106 didn't include the master-only interface promotion).
Updated table:
|| Row || Form || Case || 4.0.32 || 5.0.6 || 5.0.7-SNAPSHOT (GROOVY_5_0_X) ||
6.0.0-SNAPSHOT (master) || GEP-22 ||
| 16 | unqualified {{m(...)}} | (b) | (/) | (x) | (/) | (/) | *Documented* |
| 16b | {{this.m(...)}} | (b) | (/) | (x) | (/) | (/) | *Documented* |
| 16q | qualified {{Parent.m(...)}} | (a) | (x) ^1^ | (x) | (x) ^2^ | (/) |
*Documented* |
| - | {{Parent.super.m(...)}} | escape | (/) | (/) | (/) | (/) | *Documented* |
| - | unqualified, _exact_ {{Object}} arg | - | (/) | (/) | (/) | (/) |
*Documented* |
| D | plain class {{Child extends Parent}} | control | (/) | (/) | (/) | (/) |
_n/a_ |
^1^ Qualified on 4.0.32 _compiles_ but throws {{MissingMethodException}} at
runtime — it never fully worked there. All other cells are compile + runtime.
^2^ Qualified still fails on 5.0.x: GROOVY-12106 fixed the
unqualified/{{this.}} forms (case b), but the qualified form (case a) resolves
via the trait's _promoted interface static_, which requires GROOVY-12111 — that
is master-only and was **not** part of the 12106 backport.
h4. What the columns show
* *5.0.6* — the released, pre-fix 5.0.x baseline: case (b) and (a) both fail;
only {{super}}/exact/plain-class work.
* *5.0.x (+12106)* — the {{GROOVY_5_0_X}} tip after the backport: case (b) now
resolves (rows 16/16b flip (x) → (/)); (a) still fails pending a GROOVY-12111
backport.
* *6.0.0 (master)* — full feature set: (a) and (b) both resolve.
h4. What changed vs the previous table
* *Case (b) — rows 16 / 16b:* {{5.0.x (+12106)}} and master are now (/). 5.0.6
stays (x) (it predates the fix), making the regression-and-repair visible
across the row: 4.0.32 (/) → 5.0.6 (x) → 5.0.7-SNAPSHOT (/).
* *GEP-22 column:* was *Silent* for the (b) rows; GEP-22 now documents
inherited super-trait static resolution, so every trait row is *Documented*.
* *Case (a) — row 16q:* unchanged — (/) only on master; still (x) on every
5.0.x build (needs GROOVY-12111).
h4. Net for Grails using Groovy 5.0.x
The natural call forms (unqualified and {{this.}}) and the {{super}}/exact
forms all work on 5.0.x now. The only form still failing on 5.0.x is the
explicitly-qualified {{Parent.m(...)}}, which would require backporting
GROOVY-12111 as well.
> STC cannot resolve inherited static trait method from sub-trait body
> --------------------------------------------------------------------
>
> Key: GROOVY-12106
> URL: https://issues.apache.org/jira/browse/GROOVY-12106
> Project: Groovy
> Issue Type: Bug
> Components: Static Type Checker
> Affects Versions: 5.0.7
> Reporter: James Fredley
> Assignee: Paul King
> Priority: Major
> Labels: static-method, sts, traits
> Time Spent: 20m
> Remaining Estimate: 0h
>
> h2. Summary
> Groovy 5 static type checking does not resolve a static method declared by a
> parent trait when the method is called from a sub-trait body.
> This is independent of Grails and can be reproduced with plain Groovy traits
> under @CompileStatic.
> This was re-tested on Groovy 5.0.7-SNAPSHOT. Both an unqualified call and a
> qualified call fail static type checking:
> {code:groovy}
> inheritedStaticMethod(value)
> {code}
> {code:groovy}
> ParentTrait.inheritedStaticMethod(value)
> {code}
> The failure is distinct from GROOVY-11985, which fixed
> static-override-via-this. This issue is about resolving a parent trait's
> static method from a sub-trait body.
> h2. Standalone reproducer
> {code:groovy}
> import groovy.transform.CompileStatic
> @CompileStatic
> trait ParentTrait {
> static void configure(Closure closure, Object target) {
> if (closure != null) {
> closure.delegate = target
> closure.resolveStrategy = Closure.DELEGATE_ONLY
> closure.call()
> }
> }
> }
> @CompileStatic
> trait ChildTrait extends ParentTrait {
> void applyConfig(Closure closure, Object target) {
> configure(closure, target)
> }
> }
> @CompileStatic
> class Example implements ChildTrait {
> }
> {code}
> h2. Expected result
> The code should pass static type checking. A sub-trait should be able to
> resolve a static method declared by a parent trait.
> h2. Actual result
> Static type checking fails on the call from the sub-trait body:
> {code}
> Cannot find matching method ChildTrait#configure(groovy.lang.Closure,
> java.lang.Object)
> {code}
> Using a qualified call also fails:
> {code:groovy}
> ParentTrait.configure(closure, target)
> {code}
> h2. Real-world use case
> Apache Grails has the same pattern in the GraphQL DSL helper traits.
> Parent trait method:
> {code}
> grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ExecutesClosures.groovy
> line 34
> {code}
> {code:groovy}
> @CompileStatic
> trait ExecutesClosures {
> static void withDelegate(@DelegatesTo(strategy = Closure.DELEGATE_ONLY)
> Closure closure, Object delegate) {
> ...
> }
> }
> {code}
> Sub-traits that should be able to call the inherited helper:
> {code}
> grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Arguable.groovy
> grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ComplexTyped.groovy
> {code}
> Grails currently works around this by inlining the parent trait helper body
> into each sub-trait. Once this Groovy STC issue is fixed, that inline
> workaround can be removed.
> h2. Workaround
> Inline the static helper body in each sub-trait, or avoid calling the
> inherited static trait method from the sub-trait.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)