Scott Murphy Heiberg created GROOVY-12619:
---------------------------------------------
Summary: Compound assignment and increment on a property evaluate
the receiver expression twice
Key: GROOVY-12619
URL: https://issues.apache.org/jira/browse/GROOVY-12619
Project: Groovy
Issue Type: Bug
Affects Versions: 5.0.8, 4.0.33, 6.0.0
Reporter: Scott Murphy Heiberg
{code: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] }
def n() { obj().v++; [calls, box.v] }
}
assert new C().m() == [1, 3]
assert new C().n() == [1, 2]
{code}
Actual: m() returns [2, 3] and n() returns [2, 2]. The receiver obj() is called
once for the read of the property and again for the write. The same happens in
dynamic Groovy, under @TypeChecked and under @CompileStatic. It also happens
for prefix and postfix increment and decrement, attribute access ({{obj().@f +=
2}}), safe navigation ({{obj()?.v += 2}}), chains with a side-effecting getter,
static properties reached through an instance, and extension properties such as
File text. Under @CompileStatic, {{obj().d++}} on a BigDecimal property calls
obj() three times.
Expected: the receiver is evaluated once, before the right-hand side, and
reused for the read and the write. Subscripts already behave this way
(GROOVY-12098).
Cause: the code generator evaluated the property expression once as an rvalue
and once as the assignment target. The static compiler's rewrites to x.p =
x.p.op(y) and to the extension setter reused the receiver expression on both
sides. The elvis assignment form is GROOVY-12515.
Seen in 4.0.33, 5.0.8 and 6.0.0.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)