Scott Murphy Heiberg created GROOVY-12518:
---------------------------------------------
Summary: SC: a super property fails at runtime in a closure, and
when incremented or compound-assigned
Key: GROOVY-12518
URL: https://issues.apache.org/jira/browse/GROOVY-12518
Project: Groovy
Issue Type: Bug
Components: Static compilation
Affects Versions: 6.0.0
Reporter: Scott Murphy Heiberg
Under {{@CompileStatic}}, a property read or written through {{super}} fails at
runtime in two cases: inside a closure or lambda, and as the target of {{++}},
{{--}} or a compound assignment such as {{+=}} when the subclass declares the
same property.
{code:groovy}
class Base {
int n = 1
String name = 'base'
String getP() { 'p:base' }
}
@groovy.transform.CompileStatic
class Sub extends Base {
int n = 10
String name = 'sub'
String getP() { 'p:sub' }
String getter() { def c = { -> super.p }; c() }
String read() { def c = { -> super.name }; c() }
String write() { def c = { -> super.name = 'w' }; c(); super.name }
int inc() { super.n++ }
int add() { super.n += 5 }
}
new Sub().getter() // VerifyError
new Sub().read() // VerifyError
new Sub().write() // VerifyError
new Sub().inc() // MissingPropertyException: No such property: n for class:
Sub
new Sub().add() // MissingPropertyException: No such property: n for class:
Sub
{code}
{code}
java.lang.VerifyError: Bad invokespecial instruction: current class isn't
assignable to reference class.
{code}
In a closure the getter or setter of the superclass is called with
{{invokespecial}} from the closure class, which the JVM rejects. A super method
call in a closure, {{super.m()}}, already goes through a {{super$}} helper
method of the enclosing class; property access does not. For {{++}} and {{--}}
the property is read and written through
{{ScriptBytecodeAdapter.getPropertyOnSuper}} and {{setPropertyOnSuper}}, and
for a compound assignment it is read through {{getPropertyOnSuper}}; these
dynamic calls fail with {{MissingPropertyException}} for a statically compiled
class that declares the same property.
The same code without {{@CompileStatic}}, and with {{@TypeChecked}}, returns
{{p:base}}, {{base}}, {{w}}, {{1}} and {{6}}. Seen in 4.0.33, 5.0.8, 6.0.0 and
master. Related: GROOVY-7138 fixed {{super.m()}} in a closure with the
{{super$}} helper methods.
Expected: under {{@CompileStatic}}, {{super.name}} reads and writes the
superclass property in a closure or lambda, and {{super.n++}}, {{++super.n}}
and {{super.n += 5}} update it, in the class and in a closure, as they do in
dynamic Groovy.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)