Files
AILang/examples/tail_recur_let_wrapped_no_leak_pin.ail
T
Brummel 2488d9d345 test(codegen): RED pin for let-wrapped tail-call leak (#63 leg 2)
After the leg-1 fix (68f500c), a tail call wrapped in a trailing
`(let ...)` (or `seq`) still leaks: the arm body is an MTerm::Let, not
a direct App{tail:true}, so `arm_body_is_tail_call` (match_lower.rs
~717) is false and both the scrutinee-husk shallow-dec and the leg-1
owned-param dec are skipped — while lower_term still descends through
the Let body and emits the inner call as musttail. The scrutinee husk
and the non-forwarded owned param each leak one slab per recursion
step.

Series-free minimal repro (a plain `Box` whose replacement is
let-bound before the tail call), asserting live == 0 under
AILANG_RC_STATS=1. RED today: `allocs=6 frees=2 live=4`. This is the
leg that keeps examples/series_sma.ail at live=8 (its canonical
`(let s_new (push …) (seq … (tail-app …)))` body).

The debugger confirmed the fix is contained, not a design fork:
`arm_body_is_tail_call` feeds only the two drop-emission gates, never
the musttail-emission decision (which lives independently in
lower_term off App{tail:true}), so peeling the detection through a
trailing Let/Seq chain ending in a tail call is safe. The let
scope-close drop is gated on `!block_terminated` and so is correctly
skipped, avoiding a double-free of the let binding.

refs #63
2026-06-02 13:46:06 +02:00

19 lines
721 B
Plaintext

(module tail_recur_let_wrapped_no_leak_pin
(data Box (ctor B (con Int)))
(data IntList (ctor INil) (ctor ICons (con Int) (con IntList)))
(fn run
(type (fn-type (params (own (con Box)) (own (con IntList))) (ret (own (con Unit))) (effects IO)))
(params b input)
(body
(match input
(case (pat-ctor INil) (do io/print_str "done\n"))
(case (pat-ctor ICons v rest)
(let b_new (term-ctor Box B v)
(tail-app run b_new rest))))))
(fn main
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
(params)
(body
(let b (term-ctor Box B 0)
(app run b (term-ctor IntList ICons 1 (term-ctor IntList ICons 2 (term-ctor IntList INil))))))))