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]

Reply via email to