codeconsole opened a new pull request, #3145:
URL: https://github.com/apache/groovy/pull/3145
A compound assignment or an increment of a property evaluated the receiver
expression twice: once for the read and once for the write. This happened in
dynamic Groovy, under `@TypeChecked` and under `@CompileStatic`, and in 4.0.33,
5.0.8 and 6.0.0:
```groovy
class Box { int v = 1 }
class C {
int calls = 0
Box box = new Box()
Box obj() { calls++; box }
def m() { obj().v += 2; [calls, box.v] }
}
assert new C().m() == [1, 3] // was [2, 3]
```
The same was true of `obj().v++`, `++obj().v`, `obj().@f += 2`, `obj()?.v +=
2`, `b.inner.v += 1` with a side-effecting `getB()`, a static property reached
through an instance, and an extension property such as `obj().text += 'x'`.
Subscripts already evaluate the receiver once (GROOVY-12098).
`BinaryExpressionHelper` now evaluates the receiver of such a property once
into a temporary. This applies to compound assignment (in `eval`, before any
dispatcher-specific path) and to prefix and postfix `++` and `--`. The read and
the write then both use that temporary. Receivers without side effects stay in
place: variables (including `this` and `super`), classes, constants and a
qualified `Outer.this`. Under static compilation, `BinaryExpressionTransformer`
rewrites some compound assignments before code generation: operators that
resolve to a method, such as `String` or `BigDecimal` `+=`, and extension
properties (GROOVY-12524). Those rewrites now wrap the receiver in a
`TemporaryVariableExpression`, as GROOVY-5746 does for subscripts.
`Groovy12524` recorded the double evaluation of an extension property's
receiver and now expects a single one. The elvis assignment `?=` is left alone
(GROOVY-12515).
## Tests
`bugs.Groovy12619` covers compound assignment with several operators, the
expression value, evaluation order, prefix and postfix increment and decrement,
property chains, safe navigation, attributes, static properties, closures and
generic receivers, extension properties, and a `plusAssign` method. It runs
each case in dynamic, `@TypeChecked` and `@CompileStatic` mode and fails
without the change. So does
`Groovy12524.testCompoundAssignEvaluatesReceiverOnce`. The
`groovy.transform.stc`, `org.codehaus.groovy.classgen` (including `asm.sc`),
`org.codehaus.groovy.transform.traitx`, `groovy.operator`, `bugs` and `gls`
packages, plus the property, postfix, prefix and navigation tests in `groovy`,
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]