Failed compound arithmetic must not overwrite its target

perfloop/grol · IGNORED FAILURE

https://perfloop.ai/t/oss/case_d1j4twcp0f

Verdict

VERIFIED · settled 2026-09-26 · pull request opened as grol-io/grol#545

What happened: The assertion is violated on the comparison and satisfied with this change.

Hypothesis

A compound assignment can report an arithmetic error yet store that error where a normal value was held. Later evaluation of the same target then fails, even though the arithmetic never produced an assignable result. The prevalence of these errors in user programs is unknown.

At revision b9b1d44, `eval.State.evalAssignment` checks for an error in the incoming right-hand side, but its identifier branch passes an unchecked compound result to `env.CreateOrSet`. Its indexed branch reaches `compoundAssignNested`, which passes the unchecked result to `evalIndexAssignmentValue`. Integer division by zero returns an error from `evalInfixExpression`. The issue requires an accepted right-hand side and an operator that fails; it does not describe assignments rejected before operator evaluation.

A focused same-state `eval.EvalString` check initialized `a=[12]; x=12`, then `a[0]/=0` returned a division-by-zero error. Reading `a` afterward returned `[<err: division by zero>]`. Likewise, `x/=0` made a later read of `x` return that error. `repl.EvalOne` also accepts a reusable `State`, so a Case can exercise consecutive ordinary evaluations on one state. It should assert that the failure is reported, `a[0]` and `x` retain 12, and valid compound updates still work. An unchanged target after the failed operation would refute this claim.

Change to test: Treat an error produced by a compound operator as a failed assignment before committing it to an identifier or indexed element. Preserve the previous target value while still returning the arithmetic error.

Where it lives

perfloop/grol · repl/repl.go

Evidence

The assertion is violated on the comparison and satisfied with this change: ``On one reusable eval.State, `cfX=12`, `cfA=[12]`, and `cfM={"a":1}` followed by accepted integer `/=0` compound assignments must report division by zero without storing the error; later reads must retain the same integer values 12, [12], and 1. Successful integer `+=1` updates to each target must return and store 13, 13, and 2.``

The assertion is violated on the comparison and satisfied with this change: `With cfA initialized to [12], eval.EvalString of cfA[5]+=1 must return the exact index assignment out of bounds: 5 error and leave cfA unchanged.`

Checks: 3 of 3 passed. Verification: no defect found.

Timeline