codeconsole opened a new pull request, #3125:
URL: https://github.com/apache/groovy/pull/3125
In trait code, a property referenced from a closure ignored the closure's
delegate:
```groovy
trait T {
def cnt = 1
def m() { [cnt: 42].with { cnt } }
}
class C implements T {}
assert new C().m() == 42 // was 1
```
The same code in a class returns 42, in dynamic, `@TypeChecked` and
`@CompileStatic` code. 4.0.33, 5.0.8 and 6.0.0 return 1.
`TraitReceiverTransformer` rewrote the reference to a direct access on the
implementing instance (`$self.cnt` or the field-helper getter or setter) before
the closure's resolve strategy could apply. Assignments (`cnt = 5`) wrote the
trait property instead of the delegate's. An accessor-only property (`def
getCnt()`) failed with `ReadOnlyPropertyException` on assignment.
`TraitReceiverTransformer` now leaves a reference to an instance property of
the trait unrewritten inside a closure, whether the property is declared or
backed by an accessor. The closure is rehydrated with the implementing instance
as owner, so the reference resolves through the delegate and owner as for a
class, and the owner fallback uses the property's accessors. Lambdas and static
trait methods keep the existing rewrite. A statically compiled lambda has no
delegate and is not rehydrated. In a static method, the owner fallback would
bind to the trait interface's static accessor.
Two side effects now match classes too. `[1].each { x++ }` and `x += 2` on
an instance trait property used to lose the update (under `@CompileStatic`,
`+=` threw `GroovyCastException`). A closure now reads the property through its
getter, so an overriding getter in the implementing class is used.
## Tests
`TraitASTTransformationTest.testTraitPropertyInDelegateFirstClosure`,
`testTraitAccessorPropertyInDelegateFirstClosure`,
`testTraitPropertyInClosureFallsBackToOwner` and
`testTraitPropertyInClosureUsesAccessor` each run in dynamic, `@TypeChecked`
and `@CompileStatic` mode, and all fail without the change.
`org.codehaus.groovy.transform.traitx.*`, `groovy.transform.stc.*`,
`org.codehaus.groovy.classgen.asm.sc.*`, `gls.*`, `bugs.*` and
`groovy.ThisAndSuperTest` 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]