Skip to content

Review fixes: structural augmentation updates, interval semantics, cursor upsert, Verify - #4

Closed
ajwerner wants to merge 2 commits into
mainfrom
review-fixes
Closed

ajwerner wants to merge 2 commits into
mainfrom
review-fixes

Conversation

@ajwerner

@ajwerner ajwerner commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes for both rounds of review findings on v0.2.0. Each behavioural fix has a test; the ones that could be run against v0.2.0 in a worktree fail there.

Round one

  • Cursor.Upsert with a distinct but equal key replaced only the value and reported the new key as PrevKey. Fixed; tested with id-compared keys and a key-dependent aggregate.
  • Interval bound started from the zero endpoint: wrong for negative endpoints, a nil dereference for pointer endpoints. Explicit unset state; tested with pointer endpoints and negative spans.
  • Next/Prev on an interval iterator now end an overlap scan.
  • Verify copied the atomic reference count non-atomically. It copies only what the Updater reads; a race test verifies a snapshot during clone-and-clear.
  • SeekWhere contract tightened to what the single descent needs; ownership docs for value copies and shallow-copied keys, values and augmentations.

Round two

  • Structural changes reach ancestors: a split, merge or rebalance recomputes the restructured node and reports upward, so shape-dependent augmentations stay correct, including merges from deleting an absent key. The Updater doc states the contract. On v0.2.0 the reviewer's degree-2 example leaves the root count at 3 instead of 4.
  • Reference counts are 64-bit.
  • Empty and reversed intervals are points, so leaf matching and pruning agree wherever the interval sits.
  • Bounds.TieBreak replaces CompareIntervals and is consulted only for equal starts, since overlap searches require start order. Breaking change.
  • LowLevelIterator.Config returns a copy.
  • Verify uses the Updater's Equaler when present (NaN-safe aggregates).
  • interval.Cursor, interval.FreeList, interval.NewFreeList are nameable; the overlap cost is documented as O(log n) plus the ancestors of the k matches, up to O(k log(n/k)) when scattered.

Test plan

  • go test -race ./... on Go 1.26.8 and 1.27.1
  • New tests run against v0.2.0: cursor equal-key, pointer endpoints, overlap-after-step, Verify race and structural augmentation all fail there as expected
  • CI

🤖 Generated with Claude Code

ajwerner and others added 2 commits September 29, 2026 07:18
…ext/Prev, Verify ref copy

- Cursor.Upsert's in-place path kept the old key when the new one compared
  equal and reported the new key as PrevKey; it now replaces the key and
  reports the real previous one. Tested with keys compared by id and an
  augmentation that depends on the key.
- The interval augmentation started from the zero endpoint as its bound:
  wrong for negative endpoints and a panic for comparators that cannot
  take the zero value. subtreeBound now has an explicit unset state and
  findUpperBound reports emptiness. Tested with pointer endpoints and
  negative spans in the property test.
- interval.Iterator.Next and Prev end an overlap scan, as the seeks do.
- Verify copies only the fields the Updater reads instead of the whole
  node, whose reference count another goroutine may be changing
  atomically. A race test verifies a snapshot while the original is
  cloned, written and cleared.
- SeekWhere's documented contract now matches its single-descent
  algorithm: the predicate must be exact for spans. The aug package doc
  states that maps must not be copied by value and that keys, values and
  augmentations are shallow-copied.

Each new test fails on v0.2.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ints and TieBreak, config copy, Verify equality

- A split, merge or rebalance recomputes the restructured node and
  reports a change upward, so shape-dependent augmentations (node
  counts, heights) stay correct, including the merge caused by deleting
  an absent key. Tested with a node-counting Updater; on v0.2.0 the
  reviewer's degree-2 example leaves the root at 3 instead of 4.
- Reference counts are int64.
- An interval whose end is not after its start is a point, so leaf
  matching and subtree pruning agree wherever it sits; reversed intervals
  are points too. Tested alone in a leaf, after many splits, and reversed.
- interval.Bounds.TieBreak replaces CompareIntervals and is consulted only
  for equal start keys, since overlap searches require start order.
  Tested with a tie-breaker preferring ends.
- LowLevelIterator.Config returns a copy.
- Verify compares augmentations with the Updater's Equal when it
  implements Equaler; MonoidUpdater forwards the Monoid's. Tested with a
  NaN-propagating maximum.
- interval.Cursor, FreeList and NewFreeList are nameable; the package
  documents its overlap cost honestly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ajwerner ajwerner changed the title Fix cursor upsert of equal keys, interval zero bound, scan state, Verify ref copy Review fixes: structural augmentation updates, interval semantics, cursor upsert, Verify Sep 29, 2026
@ajwerner

Copy link
Copy Markdown
Owner Author

Folded into #5, which contains these commits and the API pass on top.

@ajwerner ajwerner closed this Sep 29, 2026
@ajwerner
ajwerner deleted the review-fixes branch September 29, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant