[ 
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)

Reply via email to