Commit Graph

1 Commits

Author SHA1 Message Date
Brummel 1be6e49b4f test(codegen): RED pin for owned-param leak in tail-recursion (#63)
An owned heap ADT param threaded through a tail-recursive fn whose
base-case arm neither forwards nor consumes it is never RC-dec'd, so
it leaks one slab per recursion step. Series-free minimal repro
(a plain `Box` ADT, no Series/RawBuf), so the pin guards the GENERAL
memory-model invariant rather than the Series surface that first
surfaced it (examples/series_sma.ail, live=8).

The pin builds the fixture with --alloc=rc, runs it under
AILANG_RC_STATS=1, and asserts live == 0 (allocs == frees). RED today:
`allocs=6 frees=4 live=2`. The fixture passes the replacement ctor
directly into the tail call (not let-bound) to isolate leg 1 — the
owned-param drop omission — from the second, distinct leg the
debugger found (a `let`-wrapped tail call also defeats the
scrutinee-husk shallow-dec gate; that leg is what pushes box_ctrl to
live=4 and series_sma to live=8, and gets its own pin once leg 1 is
green).

Cause (debugger, for the GREEN side): the fn-return Own-param dec in
crates/ailang-codegen/src/lib.rs (~1444) is gated behind
`!block_terminated`, so it fires only on the fall-through ret path;
crates/ailang-codegen/src/match_lower.rs (~805) drops only pattern
binders, never the fn's owned params. A tail-call-terminated match arm
thus has no drop site for an owned param with consume_count==0 that is
not forwarded into the tail call.

refs #63
2026-06-02 13:31:54 +02:00