Open and answer this issue on GitHub.
decision · opened 2026-10-20 · updated 2026-10-20 · 1 comment
The check analysis of benches/brc/fast.nika (0.0.1150, topic 4 of the owner’s decision round on 0.0.1151–0.0.1153) found two overflow checks a row (2.0 instructions): count += 1 and sum += temp on fields of a slot in the program’s own table (self.slots[at].count). ADR-367 bounds counters only in a grammar fold’s accumulator. Proving these checks needs a fact about every slot, such as “each slot’s count is at most the position reached”, which neither the walk nor ADR-361’s strategies (closed forms, intervals) can state today.
The owner chose a ladder:
fast.nika a struct rule (ADR-369) assert(count <= 1 << 40) together with one length check per file (assert(buf.len() <= 1 << 40)). This should prove count + 1 and sum + temp, and leave one check (the rule’s) a row instead of two. If the prover does not use the rule for overflow goals, that is a defect to fix. Try it after #714 is complete.invariant forall i :: … plus ghost var, written by the user;pragma Loop_Invariant (for all …), generated frame conditions, bounded subtypes;prove-through-loops:on (ADR-361 D10):
Vec of structs are one summary per field;count - pos <= 0 is an octagon.sum needs |sum| <= 999 · pos, a linear relation with a coefficient (polyhedra or templates). Say which of the two is needed and what each costs.
std and the tools (ADR-361 D8’s criterion: at most 5 % more instructions).fast.nika (2.0 a row), plus a histogram and a group-by over a Vec of structs written for the purpose.Depends on #767 (prove-through-loops). Nothing waits on it for 1BRC’s comparison; the motivation is the general pattern of counters and sums per key.
State as of 0.0.1174:
fast.nika, because LLVM had already removed those checks.fast.nika stands: 107.5 instructions a row (16 units, x86-64), against fast-unsafe.nika at 104.0. The only difference is the overflow checks on sum += v and count += 1 in run; with overflow checks off, fast.nika counts 104.1.Blocked: D11 over fast.nika’s hand-written Par::fold. Three questions are not settled by ADR-361 or ADR-367:
count grows inside run’s find_all loop. ADR-367 D1 defines a step count only for grammar folds.scan runs run again over a zero-padded copy of up to n - cut + MARGIN bytes, and nothing bounds the number of pieces par_pieces makes. A bound taken from bytes can therefore exceed i64.|v| <= 1023 times about 2^60 does not fit an i64. It needs ADR-367 D4’s length test before the fold, which is decided only for grammar folds.The grammar-fold case, a step that does self.slots[k].count += 1, can be built without these answers: record element-field writes as sites in fold_bound.rs. It proves nothing in fast.nika. With the gap at 3.5 instructions a row, this waits.
Generated by Claude Code