; RED fixture (refs #55, Implicit-cutover husk leak — leg B, Nil sub-case). ; ; Property under test: an owned scrutinee threaded through the ; lit-sub-pattern chain desugar must have its OUTER cell freed ; exactly once on EVERY return path — including the path that ; matches the Nil arm and touches neither inner re-match. ; ; `first_or_default` has a lit sub-pattern arm `(Cons (pat-lit 0) _)`, ; so the 16c desugar (crates/ailang-core/src/desugar.rs `desugar_match`) ; is forced off the `is_flat` fast-path: it let-binds the owned ; scrutinee `xs` into a fresh `$mp` var and lowers the arms to a chain ; of single-level matches over `$mp`. Two breakages follow once the ; param mode is `Own` (post-#55 cutover): ; 1. the `Let $mp = xs` consumes `xs` (consume_count := 1), which ; trips the codegen fn-return gate `if consume_count != 0 { ; continue }` (crates/ailang-codegen/src/lib.rs ~1522) and ; SUPPRESSES the husk free that the equivalent single-match fn ; (e.g. std_list List_map) emits as `partial_drop_(arg_xs, 2)`; ; 2. the husk obligation moves to the internal `$mp` binder, which the ; gate (it iterates `f.params` only) never inspects. ; Net effect: the outer cell of `xs` is never freed. ; ; This fixture isolates the Nil path specifically: `main` calls ; `first_or_default` with a bare `(IntList Nil)`. That path returns -1 ; and flows entry -> Nil-arm -> fn-return join, touching neither inner ; Cons re-match. The Nil cell (one 8-byte alloc) leaks -> live=1. ; The companion fixture lit_pat_ctor_tail_drop.ail covers the Cons ; path; this one pins the distinct Nil path so a Cons-only fix cannot ; pass while still leaking Nil husks. (module lit_pat_nil_scrutinee_drop (data IntList (ctor Nil) (ctor Cons (con Int) (con IntList))) (fn first_or_default (doc "Empty -> -1; first element 0 -> 0; otherwise the head.") (type (fn-type (params (borrow (con IntList))) (ret (own (con Int))))) (params xs) (body (match xs (case (pat-ctor Nil) -1) (case (pat-ctor Cons (pat-lit 0) _) 0) (case (pat-ctor Cons h _) h)))) (fn main (doc "Drive the Nil scrutinee only. Expected output: -1.") (type (fn-type (params) (ret (own (con Unit))) (effects IO))) (params) (body (seq (app print (app first_or_default (term-ctor IntList Nil))) (do io/print_str "\n")))))