---
title: Dependent-Type-Preserving Compiler Pass
url: https://www.emergentmind.com/topics/dependent-type-preserving-compiler-pass
type: topic
---

# Dependent-Type-Preserving Compiler Pass

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 $\Gamma \vdash p : \tau$ and a pass $T$ transforms $p$ to $p'$, then $p'$ remains typable at the same type, or at a translated type $\Phi(\tau)$ under a translated context $\Phi(\Gamma)$. In dependently typed settings, preservation is usually formulated with conversion rather than syntactic type equality: if $\Gamma \vdash p : \tau$ and $T(p)=p'$, then there exists $\tau'$ such that $\Gamma \vdash p' : \tau'$ and $\Gamma \vdash \tau \equiv \tau'$ [1208.0535]. 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 [1808.04006].

## 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 $\Gamma \vdash p : \tau$ and $T(p)=p'$, then $\Gamma \vdash p' : \tau$. A stronger formulation admits convertibility: if $\Gamma \vdash p : \tau$ and $T(p)=p'$, then there exists $\tau'$ such that $\Gamma \vdash p' : \tau'$ and $\Gamma \vdash \tau \equiv \tau'$. When the pass changes type structure, as in closure conversion or CPS, the preservation theorem is stated with a type/context translation $\Phi$: if $\Gamma \vdash p : \tau$ and $T(p)=p'$, then $\Phi(\Gamma) \vdash p' : \Phi(\tau)$ [1208.0535].

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 $\lambda$-abstractions by labels, or erase runtime-irrelevant arguments, while preserving the abstract dependency structure only up to $\equiv$. 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 $\Gamma \vdash M : A$ in CC then $D_d\llbracket \Gamma \rrbracket \cup D_d\llbracket M \rrbracket ; D\llbracket \Gamma \rrbracket \vdash D\llbracket M \rrbracket : D\llbracket A \rrbracket$ in DCC [2304.04574]. The same pattern appears in typed closure conversion for CC, where the forward translation preserves full-spectrum dependent types and definitional equality [1808.04006].

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 [1907.00713]. 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 $\mu F$ of a polynomial functor $F$, with separate syntax, typing, and semantics for each component [1208.0535]. Representative syntax components include sums, options, and arrays, organized as
\[
FExpr = A\ \mathbb{N} \oplus Option \oplus Sum \oplus Array,
\qquad Expr = \mu FExpr.
\]
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` [1208.0535].

This decomposition extends directly to compiler transformations. The practical recipe given in the same source defines a per-component transformation $T_i$ 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, $\forall \Gamma,e,\tau.\ WtSum(e,\tau) \wedge Tsum(e)=e' \Rightarrow Wt(coerce\ e', \tau)$ [1208.0535]. 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 [1208.0535]. 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 $\Sigma$ types, the source language reasons about functions via definitional equality and $\eta$-principles, while the target CC-CC introduces explicit code and closures [1808.04006]. Code has type
\[
Code(n : A^{env}, x : A). B,
\]
closures are values of the form `clo(code(...), env)`, and closure typing is
\[
\Gamma \vdash clo(e, env) : \Pi x : [env/n]A.\ [env/n]B.
\]
The pass preserves typing, compositionality of substitution, reduction behavior up to definitional equality, and separate compilation [1808.04006].

Defunctionalization with dependent types takes a different route. Instead of existentially hiding environments, DCC replaces $\lambda$-abstractions with first-class labels `LL{dM^}` declared in a separate label context $D$ [2304.04574]. The target keeps $\Pi$-types and universes, but no $\lambda$ in the term language. Label application reduces by looking up the body in $D$:
\[
D \vdash LL\{dM^\}\ @\ dN \triangleright dL[dM^\!/dx^\!, dN/dx].
\]
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 [2304.04574].

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 $0$ and $\omega$ distinguish erased from unrestricted usage, and the erasure function removes grade-$0$ binders, proofs, indices, and grade-$0$ components of dependent pairs [2301.02194]. Packed types such as
\[
Packed(A, R, I) \coloneqq \Sigma (r : R) .^{0} inv(r) : I
\]
erase to their carrier $R$, with the theorem: if $\Gamma \vdash t : T$ then $|\Gamma| \vdash |t| : |T|$ [2301.02194]. The Dependent Dependency Calculus generalizes this perspective with the lattice $\{\bot < C < \top\}$, separating runtime relevance, compile-time relevance, and full irrelevance, and proving erasure simulation and type preservation under stage- and dependency-indexed judgments [2201.11040].

## 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 [1610.07978]. 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 $t$ to $\tau$, then the elaborated term is well typed in Pico [1610.07978].

System DR provides a complementary perspective for GHC-like compilers by integrating roles with dependent types [1905.13706]. Equality is role-indexed, coercions are modeled as equality propositions, and representational conversion is admitted through a conversion rule analogous to
\[
\Gamma \vdash a : A,\ \Gamma ; \Delta \vdash A \equiv_{Rep} B
\Rightarrow
\Gamma \vdash a : B.
\]
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 [1905.13706].

In staged calculi, dependency is indexed by quotation depth. The calculus $\lambda^{MD}$ extends typed multi-stage programming with dependent types, stage variables, quotation, escape, stage abstraction, and cross-stage persistence $\%_\alpha$ [1908.02035]. Its judgments are explicitly stage-indexed, such as $\Gamma \vdash M : \tau @ A$ and $\Gamma \vdash \tau :: K @ A$, 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:
\[
\Gamma \vdash M:\tau@A\alpha \quad \Gamma \vdash M:\tau@A
\Rightarrow
\Gamma \vdash \%_\alpha M \equiv M : \tau@A\alpha.
\]
This supports code generators whose output types depend on persisted values from earlier stages [1908.02035].

## 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
\[
L :: Mem \Rightarrow Var \Rightarrow \{High, Low\}
\]
that depends on memory, together with a control-variable map $C$ and a ghost mode state `mds` tracking locking assumptions and guarantees [1907.00713]. 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 $R$, a concrete coupling invariant $I$, and a pacing function `abs` that decomposes a cube-shaped secure-refinement proof into more standard obligations [1907.00713]. 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 $44\%$ on the nontrivial example `EgHighBranchRevC` [1907.00713]. 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 $\phi_1,\phi_2 \in \{0,1\}$:
\[
\Sigma^{init}\ x : init(A,\phi_1).\, init(B,\phi_2).
\]
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 [2509.09059]. 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 [2509.09059]. 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 [2307.05557]. 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
\[
\Gamma \vdash \{z \Rightarrow S\} \wedge \{z \Rightarrow T\} <: \{z \Rightarrow S \wedge T\}
\qquad (\textsf{AND-BIND}),
\]
and the second is the typing rule
\[
\frac{\Gamma \vdash t : T \quad \Gamma \vdash t : U}{\Gamma \vdash t : T \wedge U}
\qquad (\textsf{AND-I'}).
\]
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 [2307.05557].

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 [2307.05557].

## 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 [1208.0535]. 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 [2304.04574].

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 [1808.04006]. Another is the use of typed administrative artifacts that are erased or ignored at runtime: coercions in Pico and System DR, grade-$0$ 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” [1610.07978].

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 [2304.04574]. The concurrent secure-compilation framework assumes SC or correctly partitioned microarchitectural state and a lock-based discipline, leaving weak memory out of scope [1907.00713]. CC-CC\_A currently models only two-word pairs and closures, not general tuple allocation or deallocation [2509.09059]. 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 [1908.02035].

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.

Source: https://www.emergentmind.com/topics/dependent-type-preserving-compiler-pass