codeconsole opened a new pull request, #3182:
URL: https://github.com/apache/groovy/pull/3182

   With `@PackedClosures` under dynamic compilation, 
`PackedClosure.setDelegate` throws `UnsupportedOperationException` for a 
delegate other than the owner, because the hoisted body binds its free names to 
the owner at compile time. `Closure.rehydrate` sets `delegate`, `owner` and 
`thisObject` on the copy directly, so it bypassed that guard and the new values 
were silently ignored:
   
   ```groovy
   class D { String foo() { 'delegate' } }
   
   @groovy.transform.PackedClosures
   class O {
       String foo() { 'owner' }
       def m(D d) {
           def c = { -> foo() }
           println c.rehydrate(d, d, d)()                   // 'owner'; 
'delegate' without packing
           println c.rehydrate(d, this, this).delegate == d // true, although 
c.delegate = d throws
       }
   }
   new O().m(new D())
   ```
   
   Seen in 6.0.0 too.
   
   `PackedClosure.rehydrate` now applies the same guard when the closure was 
packed on the dynamic trust path. A non-null delegate other than the original 
owner gets the `setDelegate` message; a non-null owner or this object other 
than the original owner gets a matching message (an unpacked dynamic closure 
resolves names through its owner and a `@CompileStatic` one through its this 
object, so both are checked). `null` and the original owner are still allowed, 
so `dehydrate()` and rehydrating back onto the original owner keep working. A 
runtime guard is used rather than a compile-time decline because a rehydrate in 
a called method (the builder idiom) is invisible to the escape walk.
   
   Closures packed under `@CompileStatic`, or on the flag's no-free-name path, 
are unchanged: they store and ignore a delegate, as before. The 
`@PackedClosures` javadoc now says rehydrate is guarded too.
   
   ## Tests
   
   `PackedClosuresTransformTest.rehydrateGoesThroughTheDelegateGuard` fails 
without the change. 
`PackedClosuresTransformTest.compileStaticRehydrateStoresAndIgnoresADelegate` 
and 
`ClosurePackCapabilityTest.syntacticallyPackedClosureCanBeRehydratedElsewhere` 
pin the unguarded paths. The closure-packing test classes, 
`groovy.lang.*Closure*`, `groovy.ClosureTest`, 
`org.codehaus.groovy.classgen.asm.sc.*` and `groovy.transform.stc.*` 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