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]