JOURNAL: 18g tidy follow-ups (stat-of-N + let-alias propagation)

Closes two of the three queued debts from the 18g tidy in the
same session. Tag-conditional partial-drop helper stays queued
— substantial, no observable fixture, all current fallback paths
cleanly use shallow ailang_rc_dec.

The 18-arc + 18g sub-arc + 18g tidy + post-tidy follow-ups are
all closed. Decision 9 has been re-framed to match the
orchestrator's dual-allocator stance (commit f10a77e). Next iter
is queue-driven; nothing load-bearing is open.
This commit is contained in:
2026-05-08 15:22:32 +02:00
parent 2e0006029b
commit ed9d6df52b
+72
View File
@@ -8279,3 +8279,75 @@ The three known debts from the 18g tidy (tag-conditional
partial-drop, let-alias-aware mode propagation, bench-number
stat-of-N) remain queued. They are RC-side improvements; none
of them block the dual-allocator stance.
## 2026-05-08 — 18g tidy follow-ups: stat-of-N + let-alias propagation
Picked off the two smaller queued debts from the 18g tidy in
the same session. The third (tag-conditional partial-drop
helper) stays queued — substantively larger, no observable
fixture, and the carve-outs it would close all fall back to
`ailang_rc_dec` cleanly (potential leak, not crash).
### Stat-of-N in the latency harness (commit `c2af5ad`)
`bench/latency_harness.py` now accepts `--runs N`. Single-run
output is byte-identical for back-compat. With N≥2 the report
prints median + min..max per cell across runs; with N≥4 the
slowest run is dropped before aggregation, matching
`bench/run.sh`'s drop-slowest convention. `bench/run.sh`
invokes the harness with `--runs 5` for each of the three
latency arms.
A 5-run smoke on the explicit-rc arm:
```
arm | median | p99(med) p99(range) | p99/median(med)
explicit @ rc (5-run) | 226.1 | 296.4 [288.7, 311.3] | 1.31×
```
The qualitative claim ("RC tail latency is 23× better than
Boehm; RC RSS is lower than Boehm") holds at this confidence
level — variance is well below the signal. The exact JOURNAL
2026-05-08 18g.2 numbers are now reproducible.
### Let-alias-aware mode propagation (commit `2e00060`)
Closes the carve-out shared by 18d.4 Iter A and 18g.1's
pre-tail-call seam: `(let a t (match a ...))` where `t` is a
non-Own fn-param defeated `scrutinee_is_owned`, because
`current_param_modes` only registered fn-params and the
let-binder `a` looked up as missing → default "owned" → arm-
close drop fired on pattern-binders whose underlying memory
the caller still owned.
Fix shape: `Term::Let` lowering inspects `value`. If `value`
is `Term::Var { name: src }` and `src` is in
`current_param_modes`, the let-binder inherits that mode for
the duration of the body. Push/pop, symmetric with `locals`.
The Borrow-aliasing case is already prevented by the
typechecker's `consume-while-borrowed` rule; the Implicit-mode
case (default for unannotated params) is what the codegen
carve-out actually surfaces, and it's what the new fixture
`rc_let_alias_implicit_param.ailx` pins.
Pre-fix on the new fixture: SIGSEGV / RC underflow on the
second iteration of `loop`. Post-fix: matches `alloc=gc`
(`0`). Kept as regression coverage. e2e count: 65 → 66.
### Remaining queued debt
- **Tag-conditional partial-drop helper.** Closes the two
dynamic-tag carve-outs (18d.4 match-arm shallow fallback
and 18g.2 App-binder partial-drop fallback). Substantial:
a per-type runtime helper that dispatches on the runtime
ctor tag and dec's non-moved ptr fields. No canonical
fixture currently hits the leak path; both fall back to
`ailang_rc_dec` (shallow) cleanly. Stays queued; will close
with the next iter that surfaces the leak in a benchmark or
a real workload.
The 18-arc + the 18g sub-arc + the 18g tidy + the
post-18g-tidy follow-ups: all closed. Decision 9 has been
re-framed (commit `f10a77e`) to match the orchestrator's
dual-allocator stance. Next iter is queue-driven; nothing
load-bearing is open.