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]