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]

Reply via email to