Paul King created GROOVY-12566:
----------------------------------
Summary: SC: super.x inside a closure or lambda throws VerifyError
Key: GROOVY-12566
URL: https://issues.apache.org/jira/browse/GROOVY-12566
Project: Groovy
Issue Type: Bug
Components: Static compilation
Affects Versions: 6.0.0, 5.1.3, 4.0.33
Reporter: Paul King
Description:
Under @CompileStatic, a property access through super inside a closure or a
lambda compiles, but the closure or lambda class fails verification when it is
loaded:
class C {
String x = 'c'
}
@groovy.transform.CompileStatic
class D extends C {
def test() {
def c = \{ -> super.x }
c()
}
}
new D().test()
java.lang.VerifyError: Bad invokespecial instruction: current class isn't
assignable to reference class.
Location:
D$_test_closure1.doCall()Ljava/lang/Object; @7: invokespecial
The closure reads its thisObject, casts it to D, and then calls C.getX() with
invokespecial. The JVM only allows invokespecial on a superclass method from
the subclass itself (D), not from the closure class. Calls to a superclass
method from inside a closure don't have this problem.
The same failure occurs, with the same message, for:
- a property with only a getter (String getY(), \{ -> super.y })
- a boolean isX() getter (\{ -> super.flag })
- a write (\{ -> super.x = 'v' })
- a closure nested in a closure (\{ -> { -> super.x }() })
- a lambda ((Supplier<String>) (() -> super.x))
These work:
- super.x outside a closure or lambda
- super.getX() and super.m() inside a closure
- super.x in a closure in dynamic Groovy or under @TypeChecked
Expected: super.x in a closure or lambda behaves as super.getX() does there,
calling the superclass's accessor (and the superclass's setter for a write).
Workaround: call the accessor explicitly, \{ -> super.getX() }, or \{ ->
super.setX(v) } for a write.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)