Dependent-Type-Preserving Compiler Pass
- Dependent-type-preserving compiler passes are transformations that ensure dependency-based typing invariants are maintained even when altering runtime representations.
- They employ modular proof composition, per-component transformations, and explicit coercions to translate source types into target types while accommodating conversion-based equality.
- Canonical cases such as closure conversion, defunctionalization, and erasure illustrate practical applications in securing concurrent, staged, and linked systems.
Searching arXiv for the cited work on dependent-type-preserving compilation, closure conversion, defunctionalization, staged calculi, and modular preservation proofs. A dependent-type-preserving compiler pass is a program transformation that preserves typing information in the presence of dependencies of types on terms, stages, effects, security labels, or runtime representations. In its simplest form, the preservation statement is: if and a pass transforms to , then remains typable at the same type, or at a translated type under a translated context . In dependently typed settings, preservation is usually formulated with conversion rather than syntactic type equality: if and , then there exists such that 0 and 1 (Schwaab et al., 2012). Across the literature, this notion appears in several distinct but related forms: modular proof composition for compiler transformations, type-preserving closure conversion and defunctionalization for the Calculus of Constructions, role- and coercion-aware preservation in GHC-like intermediate languages, erasure guided by quantitative or dependency calculi, secure refinement for concurrent value-dependent properties, and typed intermediate languages that preserve dependent invariants such as memory initialization across linking (Bowman et al., 2018).
1. Formal notion of preservation
A dependent-type-preserving pass is characterized by a typing theorem that respects dependency. The basic same-type formulation is: if 2 and 3, then 4. A stronger formulation admits convertibility: if 5 and 6, then there exists 7 such that 8 and 9. When the pass changes type structure, as in closure conversion or CPS, the preservation theorem is stated with a type/context translation 0: if 1 and 2, then 3 (Schwaab et al., 2012).
The need for conversion is a direct consequence of dependency. In systems such as CC and its variants, typing relies on reduction and definitional equality inside types. A compiler pass may normalize terms, expose closures, replace 4-abstractions by labels, or erase runtime-irrelevant arguments, while preserving the abstract dependency structure only up to 5. The source and target may therefore validate the same logical invariant using distinct syntactic types. This is explicit in defunctionalization for CC, where the theorem is: if 6 in CC then 7 in DCC (Huang et al., 2023). The same pattern appears in typed closure conversion for CC, where the forward translation preserves full-spectrum dependent types and definitional equality (Bowman et al., 2018).
A common misconception is that ordinary subject reduction suffices. In fact, several papers distinguish preservation of typing from preservation of the stronger property that the source types guarantee. For concurrent information-flow security, the relevant target theorem is not merely a typing theorem but a secure-refinement result that preserves a value-dependent hyperproperty under locking and concurrency (Sison et al., 2019). This suggests that “dependent-type-preserving” is best understood as a family of preservation principles indexed by the semantic role played by dependency.
2. Modular proof architecture
A central technique for proving preservation mechanically is modular decomposition of the language. “Modular Type-Safety Proofs using Dependant Types” reconstructs a language as a least fixpoint 8 of a polynomial functor 9, with separate syntax, typing, and semantics for each component (Schwaab et al., 2012). Representative syntax components include sums, options, and arrays, organized as
0
Each component contributes its own constructors, typing rules, and small-step rules, and the whole-language typing judgment is assembled from lifted component judgments such as WtSum, WtArray, WtOption, and WtNat (Schwaab et al., 2012).
This decomposition extends directly to compiler transformations. The practical recipe given in the same source defines a per-component transformation 1 and a per-component preservation lemma, then composes them into a whole-language theorem. For sums, constant folding is expressed component-wise, with a preservation lemma of the form: for sums, constant folding, 2 (Schwaab et al., 2012). The global compositional preservation theorem then requires coverage, compatibility of lift functions with Contains proofs, and stability of weakening, substitution, and conversion.
The mechanism is deliberately proof-engineering oriented. Contains proofs and LazyCoercion package injections such as liftSum, liftNat, liftArray, and liftOption, so that component lemmas can reason at the ambient type Expr while retaining invertibility of injections (Schwaab et al., 2012). The paper characterizes the result as a “completely mechanical approach to proof composition.” A plausible implication is that this methodology is most effective when the pass itself is structurally aligned with the functor decomposition of the source language.
3. Canonical transformations: closure conversion, defunctionalization, and erasure
Typed closure conversion and defunctionalization are the canonical examples of dependent-type-preserving passes because both alter the runtime representation of functions while trying to preserve source-level dependency. In typed closure conversion for CC with 3 types, the source language reasons about functions via definitional equality and 4-principles, while the target CC-CC introduces explicit code and closures (Bowman et al., 2018). Code has type
5
closures are values of the form clo(code(...), env), and closure typing is
6
The pass preserves typing, compositionality of substitution, reduction behavior up to definitional equality, and separate compilation (Bowman et al., 2018).
Defunctionalization with dependent types takes a different route. Instead of existentially hiding environments, DCC replaces 7-abstractions with first-class labels LL{dM^} declared in a separate label context 8 (Huang et al., 2023). The target keeps 9-types and universes, but no 0 in the term language. Label application reduces by looking up the body in 1: 2
The type-preservation theorem maps CC terms and contexts to DCC terms, contexts, and extracted labels, and the proof relies on substitution, coherence of conversion, label-context weakening, and operational correspondence via an explicit-substitution calculus CC_S (Huang et al., 2023).
Erasure-oriented passes preserve a different aspect of dependent typing: the guarantee that runtime-irrelevant invariants do not affect runtime behavior. In Quantitative Type Theory, the grades 3 and 4 distinguish erased from unrestricted usage, and the erasure function removes grade-5 binders, proofs, indices, and grade-6 components of dependent pairs (Allais, 2023). Packed types such as
7
erase to their carrier 8, with the theorem: if 9 then 0 (Allais, 2023). The Dependent Dependency Calculus generalizes this perspective with the lattice 1, separating runtime relevance, compile-time relevance, and full irrelevance, and proving erasure simulation and type preservation under stage- and dependency-indexed judgments (Choudhury et al., 2022).
4. Staging, roles, and intermediate languages
Dependent-type-preserving compilation is not confined to functional normalization passes; it also governs the design of intermediate languages. In Dependent Haskell, the target of elaboration is Pico, a dependently typed IR with explicit coercions, dependent products over type and coercion variables, and structural rather than computational definitional equality (Eisenberg, 2016). Bake, the elaboration algorithm, translates surface Dependent Haskell into type-correct Pico terms, making implicit arguments explicit, carrying equality evidence as coercions, and preserving typing across elaboration. The corresponding preservation statement is framed as soundness of elaboration: if Bake elaborates 2 to 3, then the elaborated term is well typed in Pico (Eisenberg, 2016).
System DR provides a complementary perspective for GHC-like compilers by integrating roles with dependent types (Weirich et al., 2019). Equality is role-indexed, coercions are modeled as equality propositions, and representational conversion is admitted through a conversion rule analogous to
4
Compiler passes must therefore preserve not only dependent typing but also the role discipline that licenses zero-cost coercions. The metatheory includes preservation, determinism, confluence via parallel reduction, and regularity, and the design guidance emphasizes that rewrites, inlining, specialization, and newtype unwrapping must respect role-indexed congruence and avoid representational case analysis (Weirich et al., 2019).
In staged calculi, dependency is indexed by quotation depth. The calculus 5 extends typed multi-stage programming with dependent types, stage variables, quotation, escape, stage abstraction, and cross-stage persistence 6 (Kawata et al., 2019). Its judgments are explicitly stage-indexed, such as 7 and 8, and the metatheory proves preservation, confluence, strong normalization for full reduction, and progress for staged reduction. A notable feature is that CSP erasure is not induced by reduction but by definitional equality: 9 This supports code generators whose output types depend on persisted values from earlier stages (Kawata et al., 2019).
5. Dependency beyond ordinary typing: security, concurrency, and linking
In concurrent settings, source-level dependent guarantees may be better preserved by semantic refinement than by syntactic type preservation. The framework for verifying that a compiler preserves concurrent value-dependent information-flow security formalizes the preserved property using a classification function
0
that depends on memory, together with a control-variable map 1 and a ghost mode state mds tracking locking assumptions and guarantees (Sison et al., 2019). Low-equivalence is parameterized by modes and current memory, and the per-thread property com{(tps,mds)} is defined via existence of a strong low-bisimulation closed under allowed environment interference.
Compilation is verified via concurrency-aware secure refinement rather than a syntactic target type system. The main ingredients are a refinement relation 2, a concrete coupling invariant 3, and a pacing function abs that decomposes a cube-shaped secure-refinement proof into more standard obligations (Sison et al., 2019). The mechanization in Isabelle/HOL establishes preservation of value-dependent security for a proof-of-concept While-to-RISC compiler with shared-memory concurrency and locking, and the decomposition theorem reduces proof size by 4 on the nontrivial example EgHighBranchRevC (Sison et al., 2019). The paper explicitly states that the preserved property is stronger than syntactic type preservation for concurrent settings where timing and termination leaks matter.
Typed linking introduces another extension of the concept. “Dependent-Type-Preserving Memory Allocation” develops the intermediate language CC-CC_A, where dependent pair types carry initialization flags 5: 6
The pass translates source-level dependent pairs and closures into explicit malloc, assign1, assign2, and ctag, preserving dependent typing while keeping initialization status explicit in the target (Koronkevich et al., 10 Sep 2025). Reads are typed only from initialized components, and the paper states a typed-linking safety theorem: linking against an external environment satisfying the declared types cannot introduce uninitialized reads or ill-typed closures (Koronkevich et al., 10 Sep 2025). This addresses the specific problem that type erasure during compilation otherwise prevents the linker from enforcing source-level memory-safety invariants.
6. Class-based and nominal settings
Dependent-type-preserving compilation also arises when the source language is class-based and nominal while the target is structural and dependent. The thesis “Type-Preserving Compilation of Class-Based Languages” develops a sequence of source calculi culminating in Dependent Scala and compiles them into oopslaDOT (Martres, 2023). The translation encodes classes as records with type members and methods inside a class-table object, uses refinements and recursive self types to represent nominal inheritance, and maps type selections x.L directly to DOT selections.
Two DOT extensions are introduced to make the compilation type preserving. The first is the subtyping axiom
7
and the second is the typing rule
8
The generalized type-safety theorem for DOT is adapted accordingly, and algorithmic subtyping is developed for the source calculi with unions, intersections, and type members (Martres, 2023).
The class-based case is instructive because it shows that “dependent-type-preserving” may require target-calculus extensions rather than merely a translation proof. The source of difficulty is the impedance mismatch between Scala’s nominal lookup discipline and DOT’s strict typing of selections. The resulting compilation scheme preserves dependencies carried by path-dependent types and type members, but only after adding the rules needed to express the source’s nominal invariants structurally (Martres, 2023).
7. Recurring proof obligations, mechanisms, and scope limits
Across these systems, several proof obligations recur. Substitution is fundamental: closure conversion, defunctionalization, modular optimization, staged specialization, and explicit allocation all rely on substitution lemmas that commute translation with dependent substitution (Schwaab et al., 2012). Weakening and renaming are needed whenever environments change shape. Conversion is indispensable wherever transformed terms alter normal forms or expose new definitional equalities. In systems with separate target evidence, coherence lemmas link source and target equality judgments (Huang et al., 2023).
The engineering patterns also recur. One is explicit management of environments or labels: CC-CC packages environments in closures; DCC externalizes them into a label context; CC-CC_A allocates them as initialized pairs; DOT encodes class tables as first-class objects (Bowman et al., 2018). Another is the use of typed administrative artifacts that are erased or ignored at runtime: coercions in Pico and System DR, grade-9 proofs in QTT, mds ghost state in concurrent secure refinement, and trail parameters for non-deterministic choice compiled into existential arguments in the Scala implementation of “Coming to Terms with Your Choices” (Eisenberg, 2016).
The literature also marks clear limits. Several systems omit effects, general recursion, or inductive families from the core metatheory, or require elaboration to a simpler core first (Huang et al., 2023). The concurrent secure-compilation framework assumes SC or correctly partitioned microarchitectural state and a lock-based discipline, leaving weak memory out of scope (Sison et al., 2019). CC-CC_A currently models only two-word pairs and closures, not general tuple allocation or deallocation (Koronkevich et al., 10 Sep 2025). In staged compilation, CSP erasure requires a side condition stating that a term is well typed at both the current and next stage, which usually excludes stage-bound variables (Kawata et al., 2019).
These limitations are not uniform deficiencies; they delineate the present scope of mechanically verified preservation results. A plausible implication is that future work will continue to refine the boundary between syntactic type preservation, semantic property preservation, and typed linking, rather than collapsing them into a single theorem schema.