; Iter 18g.2 RED-test fixture: a let-binder whose value is the
; result of an Own-returning fn call. 18c.3's
; `is_rc_heap_allocated` predicate returns `false` for any
; `Term::App` shape (its doc-comment explicitly defers this case
; to "later iters tied to (own) ret-mode contracts"); we now have
; those contracts (Iter 18a), and the let-scope close should drop
; the binder.
;
; Surfaced by 18f.2 / 18g.1: `bench_latency_explicit`'s
; `(let t (app build_tree 19) ...)` leaks the entire depth-19
; Tree (~1M cells) because `t` is not trackable. This minimal
; repro uses a 2-cell depth-1 tree.
;
; Pre-fix:  live = 3 (TNode + 2 TLeaf children — the depth-1
;           tree).
; Post-fix: live = 0.

(module rc_let_owned_app_leak

  (data Tree
    (ctor TLeaf)
    (ctor TNode (con Int) (con Tree) (con Tree)))

  (fn build
    (type
      (fn-type
        (params (own (con Int)))
        (ret (own (con Tree)))))
    (params d)
    (body
      (if (app eq d 0)
        (term-ctor Tree TLeaf)
        (term-ctor Tree TNode 1
          (app build (app - d 1))
          (app build (app - d 1))))))

  (fn pin
    (type
      (fn-type
        (params (borrow (con Tree)))
        (ret (own (con Int)))))
    (params t)
    (body
      (match t
        (case (pat-ctor TLeaf) 0)
        (case (pat-ctor TNode v l r) 1))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (let t (app build 1)
        (app print (app pin t))))))
