[
https://issues.apache.org/jira/browse/GROOVY-12566?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135470#comment-18135470
]
Scott Murphy Heiberg commented on GROOVY-12566:
-----------------------------------------------
PR #3049 (GROOVY-12518, https://github.com/apache/groovy/pull/3049) fixes this:
under @CompileStatic, super.x read or assigned in a closure or lambda now goes
through a super$ helper of the class instead of an invokespecial from the
closure class, and the example in the description prints c. Commit 4936199346
on that PR adds @CompileStatic to Groovy10133.testGetterVersusIsser10 and
ThisAndSuperTest.testSuperDotPropertyWithOverloadedSettersInClosure; both fail
without the PR's changes and pass with them.
> 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: 4.0.33, 5.1.3, 6.0.0
> Reporter: Paul King
> Priority: Major
>
> 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:
> {code:groovy}
> class C {
> String x = 'c'
> }
> @groovy.transform.CompileStatic
> class D extends C {
> def test() {
> def c = { -> super.x }
> c()
> }
> }
> new D().test()
> {code}
> 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)