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]

Reply via email to