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]