Scott Murphy Heiberg created GROOVY-12660:
---------------------------------------------
Summary: SC closure packing calls methods resolved against a
closure object on the owner class (TO_SELF, nested closures, Closure methods)
Key: GROOVY-12660
URL: https://issues.apache.org/jira/browse/GROOVY-12660
Project: Groovy
Issue Type: Bug
Affects Versions: 6.0.0, 7.0.0-alpha-1
Reporter: Scott Murphy Heiberg
With closure packing ({{@PackedClosures}} or
{{-Dgroovy.target.closure.pack=true}}), a statically compiled closure body is
hoisted into a method of the owner class. Calls that the type checker resolved
against a closure object are then compiled as if they targeted the owner.
{code:groovy}
@groovy.transform.CompileStatic
class C {
String toString() { 'C' }
static Object self(@DelegatesTo(value=String, strategy=Closure.TO_SELF)
Closure c) { c.resolveStrategy = Closure.TO_SELF; c() }
Object a() { self { -> toString() } }
Object b() { Closure<String> outer = { -> { -> toString() }() }; [outer(),
outer.toString()] }
Object c() { Closure c = { -> memoize() }; c() }
}
{code}
*Actual*, with packing:
* {{a()}} returns {{C}}.
* {{b()}} throws {{MissingPropertyException: No such property: owner for class:
C}} (on 6.0.0 it returns {{C}} for the inner call).
* Loading {{C}} fails with {{VerifyError: Bad type on operand stack ... Type
'C' is not assignable to 'groovy/lang/Closure'}}.
*Expected*, as without packing and in dynamic Groovy: {{a()}} returns the
closure's own toString(), {{b()}} returns the outer closure's toString() twice,
{{c()}} returns the memoized closure.
Cause: the packing decision only checks for delegate-resolved names and for the
named closure pseudo-properties. It does not decline a call resolved against
the closure itself: an Object method under TO_SELF, an Object method in a
nested closure (resolved against the enclosing closure since GROOVY-12576), or
a method that Closure declares.
Verified on 6.0.0 and master.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)