codeconsole opened a new pull request, #3184:
URL: https://github.com/apache/groovy/pull/3184
In dynamic code, `@PackedClosures` hoists a closure into a method of the
owner class on the annotation's word. Calls that dynamic Groovy resolves
against a closure object then reach the owner instead:
```groovy
class C {
String toString() { 'C' }
@groovy.transform.PackedClosures Object m() { Closure outer = { -> { ->
toString() }() }; [outer(), outer.toString()] }
@groovy.transform.PackedClosures Object mem() { def c = { -> memoize()
}; c() }
}
new C().m() // [C, C.$packed$closure$0@…]: the owner's toString, not the
outer closure's
new C().mem() // MissingMethodException: No signature of method: memoize
for class: C
```
The same happens for other methods `Closure` declares (`curry`, `dehydrate`,
`rehydrate`, `asWritable`, `trampoline`, `rightShift`) and recursion through
`call`/`doCall` (`clone()` calls `Object.clone()` on the owner); for bare
`maximumNumberOfParameters` and `parameterTypes`, which throw
MissingPropertyException; and for `hashCode()`, `equals()`, `getClass()` and
GDK methods such as `with` or `is` in a nested closure, which
`ClosureMetaClass` answers on the enclosing closure while in a hoisted body the
nested closure's owner is the owner instance. Seen in 6.0.0 too.
The dynamic path of the packing decision (`ClosureWriter.isPackTriggered`)
now declines such a closure. The check is by name, since there are no types: in
the closure's own body, an implicit-this call to a public `Closure` method that
`Object` does not declare, or to `doCall`, or a read of a `Closure` property;
in a closure nested directly in the body, an implicit-this call to an `Object`
method or to a GDK method a closure has (`print`, `println` and `printf` are
excluded, because their `Closure` versions forward to the owner). `Object` and
GDK methods called in the closure's own body go to the owner first and still
pack. `ClosureWriter.triggerDeclineReason` gives the reason to WARN and STRICT.
The `@CompileStatic` writer is unchanged; #3181 (GROOVY-12660) covers it.
## Tests
`PackedClosuresTransformTest.dynamicClosuresCallingClosureMethodsDecline`,
`dynamicClosuresCallingObjectMethodsInANestedClosureDecline` and
`strictModeReportsDynamicClosureReceiverDecline` fail without the change; the
second also checks that owner-resolved shapes still pack. The packing test
classes, `groovy.lang.*Closure*`, `groovy.ClosureTest`,
`groovy.transform.stc.*` and `org.codehaus.groovy.classgen.asm.sc.*` pass. The
Checkstyle and CodeNarc gates pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]