Stage 2 of the 4-stage Phase 3b resolution plan per #235. Parallel track — L4-driven independent of Stage 1. Owner-approved 2026-05-30.
Motivation
Phase 3b's design gap (#235) traces to a deeper L4 question: should TFunEff's R_in / R_out slots be type-level only (current state — derived from typing premises) or program-level commitments (the L4 ProgramMode labelling vector)?
L4's existing direction — type-level commitments become program-level — aligns with extending ELam to carry R_in / R_out syntactically. Stage 2 makes that extension.
AST change
(* before *)
| ELam : ty -> expr -> expr
(* after *)
| ELam : ty -> region_env -> region_env -> expr -> expr
(* T_param R_in R_out body *)
Required cascading changes
| Layer |
Change |
formal/Syntax.v |
ELam constructor + Fixpoints (free_vars, shift, subst, regions_introduced_by) |
formal/Syntax.v |
NEW declared_lambda_r_ins : expr -> list region_name Fixpoint (Stage 3 dependency) |
formal/TypingL1.v |
T_Lam_L1_* and T_Lam_L1_*_Eff rules: premise enforces annotation matches body's actual R_in/R_out (no drift). Programs using non-Eff lambdas can default to R_in = R, R_out = R (or [] if cleaner). |
formal/Semantics.v |
NOT TOUCHED per owner directive — legacy judgment stays. |
formal/Semantics_L1.v |
inversion (T_Lam_L1_*) patterns (~28 cases): mechanical update for the new arity. Existing proofs stay Qed. |
formal/TypingL2.v |
T_App_L2_Eff β-case inversion: pulls R_in/R_out from the syntactic annotation rather than the typing premise (proof simplifies). |
lib/borrow.ml / Rust crates |
ELam constructor in Rust AST + OCaml parser. Cross-language sync. |
| Codegen |
typed-wasm emitter: encode R_in/R_out in the lambda's metadata (or no-op if metadata already type-derived). |
Drift prevention
The typing rule premise enforces annotation ≡ derived R_in/R_out. Shifted/substituted lambdas keep their annotation (it's syntax — shift/subst pass through). Any operation that would CHANGE R_in/R_out (e.g. region-substitution during reduction) must update the annotation accordingly.
Migration path
Optional NEW constructor EAnnotLam could ship first as a graceful migration if breaking existing programs is undesirable. Owner decision: bigbang vs phased AST migration.
Out of scope
- Phase 3b lemma changes: those are Stage 3 (#TBD).
- Unconditional preservation_l2: Stage 4 (#TBD).
- Stage 2 ships only the AST + typing-rule + downstream cascading. Phase 3b's lemma continues to use Stage 1's
tfuneff_lambda_free until Stage 3.
Owner-directive compliance
- ✅ Modifies
TypingL1.v (post-redesign judgment) — not Typing.v (legacy).
- ✅ Does NOT touch
Semantics.v / Counterexample.v (legacy).
- ✅ Does NOT introduce
Axiom or Admitted.
- L4-aligned per
formal/PRESERVATION-DESIGN.md §7.
References
🤖 Generated with Claude Code
Stage 2 of the 4-stage Phase 3b resolution plan per #235. Parallel track — L4-driven independent of Stage 1. Owner-approved 2026-05-30.
Motivation
Phase 3b's design gap (#235) traces to a deeper L4 question: should TFunEff's
R_in/R_outslots be type-level only (current state — derived from typing premises) or program-level commitments (the L4 ProgramMode labelling vector)?L4's existing direction — type-level commitments become program-level — aligns with extending
ELamto carryR_in/R_outsyntactically. Stage 2 makes that extension.AST change
Required cascading changes
formal/Syntax.vELamconstructor + Fixpoints (free_vars,shift,subst,regions_introduced_by)formal/Syntax.vdeclared_lambda_r_ins : expr -> list region_nameFixpoint (Stage 3 dependency)formal/TypingL1.vT_Lam_L1_*andT_Lam_L1_*_Effrules: premise enforces annotation matches body's actual R_in/R_out (no drift). Programs using non-Efflambdas can default toR_in = R, R_out = R(or[]if cleaner).formal/Semantics.vformal/Semantics_L1.vinversion (T_Lam_L1_*)patterns (~28 cases): mechanical update for the new arity. Existing proofs stay Qed.formal/TypingL2.vT_App_L2_Effβ-case inversion: pulls R_in/R_out from the syntactic annotation rather than the typing premise (proof simplifies).lib/borrow.ml/ Rust cratesELamconstructor in Rust AST + OCaml parser. Cross-language sync.Drift prevention
The typing rule premise enforces annotation ≡ derived R_in/R_out. Shifted/substituted lambdas keep their annotation (it's syntax — shift/subst pass through). Any operation that would CHANGE R_in/R_out (e.g. region-substitution during reduction) must update the annotation accordingly.
Migration path
Optional NEW constructor
EAnnotLamcould ship first as a graceful migration if breaking existing programs is undesirable. Owner decision: bigbang vs phased AST migration.Out of scope
tfuneff_lambda_freeuntil Stage 3.Owner-directive compliance
TypingL1.v(post-redesign judgment) — notTyping.v(legacy).Semantics.v/Counterexample.v(legacy).AxiomorAdmitted.formal/PRESERVATION-DESIGN.md§7.References
formal/L4.v+formal/L4-DYADIC.md— L4 ProgramMode labelling discipline.formal/PRESERVATION-DESIGN.md§7 — L4 design vision.feedback_zig_apis_ffis_idris2_abismemory — boundary-tool philosophy (annotations as ABI commitments).🤖 Generated with Claude Code