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

   A compound assignment, increment or decrement of a trait field inside a 
closure or lambda lost the update or failed:
   
   ```groovy
   trait T {
       private int x = 1
       def m() { [1].each { x++ }; [1].each { x += 2 }; x }
   }
   class C implements T {}
   new C().m()
   ```
   
   Dynamic Groovy returns 1. With `@CompileStatic` the `+=` throws 
`GroovyCastException: Cannot cast object '3' with class 'java.lang.Integer' to 
class 'T'`. For a static field, or in a lambda, `@CompileStatic` fails at 
compile time instead. 4.0.33, 5.0.8 and 6.0.0 behave the same.
   
   In a trait method body, `NAryOperationRewriter` rewrites `x op= y` into `x = 
x op y` and rejects prefix and postfix operations on trait fields. It did not 
visit closure bodies, because `ClassCodeExpressionTransformer.transform` leaves 
a `ClosureExpression` untouched. `TraitReceiverTransformer` then turned the 
field into a field-helper getter call, and the operator was applied to the call 
result.
   
   `NAryOperationRewriter` now visits closure and lambda bodies. Inside them it 
rewrites a compound assignment only when the target is a trait field, so other 
targets keep their compound semantics. It applies the existing prefix/postfix 
rejection there too. `x += 2` now updates the field in all compile modes. `x++` 
inside a closure gets the same compile error as in a method body, which is the 
documented limitation ("Prefix and postfix operations" in the traits guide).
   
   #3125 (GROOVY-12598) leaves trait properties referenced from a closure for 
the closure to resolve, which would let `x++` on a property work there. If both 
land, the closure-level prefix/postfix rejection can skip properties when not 
in a lambda.
   
   ## Tests
   
   `TraitASTTransformationTest.testCompoundAssignmentOfTraitFieldInClosure` 
(dynamic, `@TypeChecked`, `@CompileStatic`) and 
`TraitASTTransformationTest.testPrefixOrPostfixOfTraitFieldInClosure` fail 
without the change. They cover private, public and static fields, instance and 
static methods, closures and lambdas. `org.codehaus.groovy.transform.traitx.*`, 
`TraitsSpecificationTest`, `groovy.transform.stc.*`, 
`org.codehaus.groovy.classgen.asm.sc.*` 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