Skip to content

Sum: fold constants without modifying shared objects, drop constants that cancel - #734

Merged
evaleev merged 3 commits into
masterfrom
fix/sum-constant-fold
Oct 26, 2026
Merged

evaleev merged 3 commits into
masterfrom
fix/sum-constant-fold

Conversation

@evaleev

@evaleev evaleev commented Oct 26, 2026

Copy link
Copy Markdown
Member

Follow-up to #732, stacked on its branch; retarget to master once it lands. Both fixes are pre-existing behaviors of the constant-merge path that #732 made reliably reachable.

Folding modified a constant the caller still holds. The move-only Sum ctor does not clone its summands, and later constants were added into the recorded one in place. Through transform_sum_expr, a range holding Constant(1), Constant(2) and x produced 3 + x and left the range's first element equal to 3. HashingAccumulator (Wick, bernoulli.cpp) reaches the same ctor. The fold now builds a new Constant and swaps it in; append/prepend were already safe because they clone, and now share the same code.

Constants that cancel were kept as a zero summand. Constant(1), Constant(-1), x gave the two-term sum 0 + x, although the ctor documents that zeros are omitted; append and prepend did the same. The recorded constant is now erased once it is zero and the slot released, so a later constant starts a new one. A sum of nothing but cancelling constants becomes an empty Sum rather than Sum{0}.

Three commits: the shared fold_constant helper (refactor only), the non-mutating fold, and the zero drop. Each behavior commit carries a test that fails against its parent.

The move-only ctor, append and prepend each repeated the assert and the
in-place addition into the summand recorded by constant_summand_idx_.
Route all three through a private fold_constant helper.
The move-only ctor does not clone its summands, so the constant it records
may still be held by the caller, and adding later constants into it in
place changed the caller's object: transform_sum_expr over a range holding
Constant(1) and Constant(2) left the range's first element equal to 3.
Build the folded constant as a new object and swap it in.
The move-only ctor, append and prepend omit zero summands on input but
kept a constant that reached zero by folding, so Constant(1), Constant(-1)
and x produced the two-term sum 0 + x although the ctor documents that
zeros are omitted. Erase the recorded constant once it is zero and clear
the record, so a later constant starts a new slot.
@evaleev evaleev added the bug Something isn't working label Oct 26, 2026
@evaleev evaleev added this to the 26.2 milestone Oct 26, 2026
Base automatically changed from ajay/sum-move-erase to master October 26, 2026 14:12
@evaleev
evaleev merged commit c939ec4 into master Oct 26, 2026
18 of 20 checks passed
@evaleev
evaleev deleted the fix/sum-constant-fold branch October 26, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant