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

   Under `@CompileStatic`, `++` and `--` on a non-primitive property or 
subscript element evaluated the operand twice:
   
   ```groovy
   @groovy.transform.CompileStatic
   class Box {
       int gets = 0
       BigDecimal d = 1
       BigDecimal getD() { gets++; d }
       void setD(BigDecimal v) { d = v }
   }
   @groovy.transform.CompileStatic
   def m() { def b = new Box(); b.d++; [b.gets, b.@d] }
   assert m() == [1, 2]   // was [2, 2]
   ```
   
   For a subscript such as `list[idx++]++` on a `List<Integer>`, the receiver 
and index expressions ran again too, so the incremented value of the next 
element was stored into the first one (`[2, [21, 20], 10]` instead of `[1, [11, 
20], 10]`). Dynamic Groovy and `@TypeChecked` read the operand once. 4.0.33, 
5.0.8 and 6.0.0 behave the same.
   
   When STC has resolved `next()`/`previous()`, 
`StaticTypesBinaryExpressionMultiTypeDispatcher.writePostOrPrefixMethod` popped 
the value already loaded and called the method on the operand expression again. 
It now stores that value in a temporary and makes the call on it, with the same 
method target, as `emitCompoundAssignCall` in the same class does. Postfix 
still yields the old value and prefix the new one. Primitive operands and the 
dynamic and `@TypeChecked` code generation are unchanged.
   
   This and #3145 (GROOVY-12619, receiver of a compound-assigned or incremented 
property evaluated once) touch different files; together, `obj().d++` evaluates 
both the receiver and the getter once.
   
   ## Tests
   
   The new tests in `STCAssignmentTest` run under `@TypeChecked` and, through 
`AssignmentsStaticCompileTest`, under `@CompileStatic`. Four of them fail under 
`@CompileStatic` without the change: 
`testPostfixAndPrefixOnPropertyCallGetterOnce`, 
`testPostfixAndPrefixOnPropertyCallGetterOnce2`, 
`testPostfixAndPrefixOnSubscriptCallGetAtOnce` and 
`testPostfixAndPrefixOnSubscriptEvaluateIndexOnce`. Between them they cover 
wrapper, BigDecimal, String, Character and custom `next()` properties, static 
properties, closures, lambdas, safe navigation, a custom getAt/putAt, and lists 
and arrays with a side-effecting index. `testPostfixAndPrefixOnLocalVariable` 
guards locals. The `groovy.transform.stc`, `org.codehaus.groovy.classgen.asm` 
(including `.sc`), `gls`, `groovy.bugs` and `groovy.operator` packages 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