[
https://issues.apache.org/jira/browse/GROOVY-12518?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Scott Murphy Heiberg updated GROOVY-12518:
------------------------------------------
Description:
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.
PR: https://github.com/apache/groovy/pull/3049
was:
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.
PR: https://github.com/apache/groovy/pull/3049 (split out of
https://github.com/apache/groovy/pull/3044)
> 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
> Priority: Major
>
> 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.
> PR: https://github.com/apache/groovy/pull/3049
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)