Files
AILang/bench
Brummel eba1be8d9d feat(codegen): fill MArg.mode for App args, read the anon-temp drop gate off it, delete module_def_ail_types (mir.3b)
Second of two iterations delivering spec 0060's mir.3 row (plan
docs/plans/0118-mir.3b-marg-mode-and-table-delete.md). lower_to_mir's
Term::App arm fills each MArg.mode from the resolved callee's
param_modes (the sig = synth_pure(callee) it already holds); codegen's
emit_call anon-temp borrow-slot drop gate reads arg.mode instead of
re-looking-up the callee's param_modes from the module_def_ail_types
table; and — since that gate was the table's only reader — the
module_def_ail_types field plus all its construction and threading are
deleted.

Two refinements to the spec's mir.3b sketch, settled in planning from a
focused recon and recorded in spec 0060:

1. module_def_ail_types is deleted in mir.3b, not mir.5. A grep proved
   self.module_def_ail_types had exactly ONE reader (the anon-temp
   gate); the own-param drop reads param_modes from the def's own f.ty,
   not this table. Once the gate moves onto MArg.mode the table is dead,
   so it is removed now rather than carried as dead code to mir.5. The
   mir.5 row's "last re-derivation residue" shrinks to the
   element-type / Term::New (New.elem) work.

2. MArg.mode is filled for App args only; MTerm::Let.mode is not filled.
   Only App args have a real per-arg mode source (the callee
   Type::Fn.param_modes). Do args (EffectOpSig has no param modes), Ctor
   args (no per-field mode), and Recur args (loop binders carry no mode)
   stay Mode::Owned. Let.mode has no source (ast::Term::Let has no mode
   field) and no consumer (the let-drop gate reads consume, not
   Let.mode), so it stays Owned — filling it would invent a value
   nobody reads.

Safety property held: MArg.mode is filled from the same callee fn-type
the gate read from the table, so the drop fires identically. For
(app RawBuf.get (app RawBuf.set …) 0), RawBuf.get's param 0 is borrow,
so args[0].mode = Borrow — exactly the value module_def_ail_types
yielded. Confirmed by the anon-temp witness staying green.

ParamMode -> Mode conversion: Borrow -> Mode::Borrow; Own and Implicit
(the Implicit ≡ Own contract) -> Mode::Owned. The own-param drop keeps
reading ParamMode off f.ty (Type/ParamMode imports retained, live
readers at lib.rs:1356/1507).

Also retires three now-stale doc comments that named the deleted
module_def_ail_types field (ailang-check/src/lib.rs, uniqueness.rs, and
the codegen_import_map_fallback_pin test doc) — a direct consequence of
the deletion, reworded to the current architecture.

Verification (orchestrator, post-implement inspect): diff matches the
plan (App-arg m_args built before m_callee consumes sig — the benign
borrow-order deviation the plan's note flagged); module_def_ail_types
grep-clean across all of crates/; cargo build --workspace clean (no
unused/dead_code); cargo test --workspace 702 passed / 0 failed / 3
ignored (+1 = the new producer pin app_arg_carries_callee_borrow_mode;
no #[ignore] added). The anon-temp drop-correctness witness
raw_buf_owned_drop_balances_rc_stats stays live=0, now driven by
MArg.mode; the other RC-stats leak pins green; #49 stays #[ignore]
(mir.4); #51/#53 build guards green.

mir.3 is now complete (3a relocated consume_count + deleted the second
uniqueness run; 3b filled the mode annotation + deleted
module_def_ail_types). Remaining: mir.4 (#49 StrRep RED->GREEN),
mir.5 (element-type/Term::New + ledger).
2026-05-31 20:10:25 +02:00
..