[
https://issues.apache.org/jira/browse/GROOVY-12104?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King updated GROOVY-12104:
-------------------------------
Description:
Inside a trait STATIC method, an unqualified `super.m(...)` call does
not walk the trait chain documented for the instance-method case
(GEP-22 § "this, super, and stackable traits" item 2). The call
compiles successfully but throws MissingMethodException at runtime.
Minimal reproducer:
{code:groovy}
trait Base { static String m() { 'Base' } }
trait V extends Base {
static String m() { 'V' }
static callSuper() { super.m() } // unqualified, from static
}
class Impl implements V { }
Impl.callSuper()
{code}
Expected: either resolve to Base.m (matching the spec's "walks the
trait chain" semantic for the instance case) or reject at compile
time as an unsupported construct.
Actual (consistent across 4.0.32, 5.0.6, 6.0.0-alpha-1):
java.lang.MissingMethodException: No signature of method:
static Base.m() is applicable for argument types: () values: []
Contrast: the instance-method version of the same shape
(without `static`) works as the spec documents — returns 'Base'.
Plain Java/Groovy `super.m()` for class statics works normally
(returns the parent class's m()), so the limitation is specific to
trait static methods.
*Recommended fix*: either implement the trait-chain walk for statics
(symmetric with the instance-method case), or reject at compile time
with a clear error pointing to `T.super.m(...)` as the explicit form.
The latter is simpler and matches the recommendation in the GEP-22 v5
draft (§ "this, super, and stackable traits" item 4, already drafted
as part of the GEP-22 PR companion to this ticket).
*Test coverage*: row 15 in
src/test/groovy/org/codehaus/groovy/transform/traitx/TraitStaticDispatchMatrix.groovy
is currently @NotYetImplemented asserting the compile-error
end-state; will flip red when this ticket is resolved.
*Related*: GROOVY-11985, GROOVY-12093, JIRA #1 (T.this in trait body).
Both surfaced during empirical sweep for Grails alternatives.
was:
Inside a trait body, the qualifier syntax `T.this.<member>` (where T
is the enclosing trait) compiles successfully but produces invalid or
mis-typed bytecode that fails at runtime.
Minimal reproducer:
{code:groovy}
trait V {
static boolean defaultNullable() { false }
static seen() { V.this.defaultNullable() }
}
class Over implements V { static boolean defaultNullable() { true } }
Over.seen()
{code}
Expected: either return a value matching a defined semantic, or reject
at compile time as a syntax error (T.this has no coherent meaning in
trait code per GEP-22, where `this` is the implementing instance and
the trait is not an enclosing scope).
Actual:
* Groovy 4.0.32: java.lang.VerifyError "Bad type on operand stack"
(Type 'java/lang/Class' not assignable to 'groovy/lang/Closure'
at V$Trait$Helper.seen(Ljava/lang/Class;)Ljava/lang/Object; @1: invokevirtual)
* Groovy 5.0.6 / 6.0.0-alpha-1: java.lang.ClassCastException:
Cannot cast java.lang.Class to V
* Bytecode disassembly: 2ab6 0032 c000 09ba 003f 0000 b0
(aload_0 of $static$self (Class) → invokevirtual expecting Closure)
The bug shape changed between 4.x and 5.x — the verifier-level
mismatch on 4.x was apparently fixed but the underlying transform
still produces wrong code (now ClassCastException at runtime).
Discovered during the GROOVY-11985 / GROOVY-12093 thread when
enumerating candidate alternatives Grails could use as workarounds
for trait-body static dispatch (Eric Milles' comment of 25-Jun-2026
asked whether `Validateable.this.defaultNullable()` would work).
*Recommended fix*: reject T.this.* in trait code at compile time.
For "force the trait's own implementation", `T.super.m(...)` is the
existing supported form. For normal dispatch, `this.m(...)` (which
follows row-1 override-visible dispatch).
*Proposed spec text*: GEP-22 v5 § "this, super, and stackable traits"
item 4 (already drafted as part of the GEP-22 PR companion to this ticket).
*Test coverage*: row 14 in
src/test/groovy/org/codehaus/groovy/transform/traitx/TraitStaticDispatchMatrix.groovy
is currently @NotYetImplemented asserting the compile-error
end-state; will flip red when this ticket is resolved (the cue to
drop @NotYetImplemented).
> Trait body with T.this.* qualifier produces VerifyError (4.x) /
> ClassCastException (5.x/6.x) — should be a compile error
> ------------------------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12104
> URL: https://issues.apache.org/jira/browse/GROOVY-12104
> Project: Groovy
> Issue Type: Improvement
> Reporter: Paul King
> Priority: Major
>
> Inside a trait STATIC method, an unqualified `super.m(...)` call does
> not walk the trait chain documented for the instance-method case
> (GEP-22 § "this, super, and stackable traits" item 2). The call
> compiles successfully but throws MissingMethodException at runtime.
> Minimal reproducer:
> {code:groovy}
> trait Base { static String m() { 'Base' } }
> trait V extends Base {
> static String m() { 'V' }
> static callSuper() { super.m() } // unqualified, from static
> }
> class Impl implements V { }
> Impl.callSuper()
> {code}
> Expected: either resolve to Base.m (matching the spec's "walks the
> trait chain" semantic for the instance case) or reject at compile
> time as an unsupported construct.
> Actual (consistent across 4.0.32, 5.0.6, 6.0.0-alpha-1):
> java.lang.MissingMethodException: No signature of method:
> static Base.m() is applicable for argument types: () values: []
> Contrast: the instance-method version of the same shape
> (without `static`) works as the spec documents — returns 'Base'.
> Plain Java/Groovy `super.m()` for class statics works normally
> (returns the parent class's m()), so the limitation is specific to
> trait static methods.
> *Recommended fix*: either implement the trait-chain walk for statics
> (symmetric with the instance-method case), or reject at compile time
> with a clear error pointing to `T.super.m(...)` as the explicit form.
> The latter is simpler and matches the recommendation in the GEP-22 v5
> draft (§ "this, super, and stackable traits" item 4, already drafted
> as part of the GEP-22 PR companion to this ticket).
> *Test coverage*: row 15 in
> src/test/groovy/org/codehaus/groovy/transform/traitx/TraitStaticDispatchMatrix.groovy
> is currently @NotYetImplemented asserting the compile-error
> end-state; will flip red when this ticket is resolved.
> *Related*: GROOVY-11985, GROOVY-12093, JIRA #1 (T.this in trait body).
> Both surfaced during empirical sweep for Grails alternatives.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)