Skip to content

Commit 4bd538b

Browse files
hyperpolymathclaude
andcommitted
docs: sync whitepaper body with actual Idris2 ABI names
- Replace Schema/TypedGet/GetHere/GetThere listings with actual implementation names: Schema=List Field, FieldIn/FieldHere/FieldThere - Add AllocResult to the QTT listing to show the full alloc/free protocol - Expand freeRegion description to explain Level9/Level10 composition - Add (1 _) quantity annotation to Linear.idr freeRegion — enforces exactly-once handle use at the type level (prevents leak and double-free) - Update date from March 2026 to April 2026 - Apply all changes to both docs/whitepapers/academic/ and docs/arxiv/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0a80848 commit 4bd538b

3 files changed

Lines changed: 67 additions & 27 deletions

File tree

docs/arxiv/typed-wasm.tex

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -738,24 +738,31 @@ \subsection{Idris~2 and Dependent Types}
738738
within the bounds of array of size~$n$'' is a proposition over the value
739739
of~$i$.
740740

741-
A region schema is a value-level record:
741+
A region schema is a flat list of named, typed fields:
742742

743-
\begin{lstlisting}[language=Idris2,caption={Region schema as a dependently typed list.}]
744-
data Schema : List (String, FieldType) -> Type where
745-
Nil : Schema []
746-
(::) : Field name ty -> Schema rest -> Schema ((name, ty) :: rest)
743+
\begin{lstlisting}[language=Idris2,caption={Region schema as a list of named fields.}]
744+
-- Schema is a list of fields; order determines memory layout.
745+
Schema : Type
746+
Schema = List Field
747+
748+
data Field : Type where
749+
MkField : (name : String) -> (ty : WasmType) -> Field
747750
\end{lstlisting}
748751

749-
A typed access is indexed by the schema:
752+
A compile-time field-lookup proof witnesses that a named field exists
753+
in the schema (Level~2 region-binding safety):
750754

751-
\begin{lstlisting}[language=Idris2,caption={Typed memory access indexed by schema.}]
752-
data TypedGet : Schema fields -> (name : String) -> FieldType -> Type where
753-
GetHere : TypedGet (MkField {name} {ty} :: rest) name ty
754-
GetThere : TypedGet rest name ty -> TypedGet (f :: rest) name ty
755+
\begin{lstlisting}[language=Idris2,caption={Field-lookup proof for Level~2 region-binding.}]
756+
data FieldIn : String -> Schema -> Type where
757+
FieldHere : {auto prf : fieldName f = name}
758+
-> FieldIn name (f :: rest)
759+
FieldThere : FieldIn name rest -> FieldIn name (f :: rest)
755760
\end{lstlisting}
756761

757762
The result type of \texttt{region.get \$r .name} is \emph{computed} from
758-
the schema, not declared by the programmer.
763+
the schema via \texttt{FieldIn} --- not declared by the programmer.
764+
Without a valid \texttt{FieldIn} proof, the access is rejected at compile
765+
time.
759766

760767
\subsection{Quantitative Type Theory}
761768

@@ -776,14 +783,23 @@ \subsection{Quantitative Type Theory}
776783
\end{tabular}
777784
\end{table}
778785

779-
Level~10 is implemented by binding allocation handles with quantity~1:
786+
Level~10 is implemented by binding allocation handles with quantity~1.
787+
The allocation protocol produces a linear handle plus a liveness witness;
788+
freeing consumes both:
789+
790+
\begin{lstlisting}[language=Idris2,caption={Linear resource protocol: alloc produces, free consumes.}]
791+
data AllocResult : (token : Nat) -> Type where
792+
MkAllocResult : LinHandle token -> RegionLive token -> AllocResult token
780793

781-
\begin{lstlisting}[language=Idris2,caption={Linear resource handling via QTT quantity~1.}]
794+
-- (1 _) enforces exactly-once use: zero = leak, two = double-free.
782795
freeRegion : (1 _ : LinHandle token) -> RegionLive token -> FreeResult
783796
\end{lstlisting}
784797

785798
The \texttt{(1 \_)} annotation means the type checker rejects any program
786799
where the handle is used zero times (leak) or more than once (double-free).
800+
After \texttt{freeRegion} returns, the \texttt{RegionLive} token is also
801+
consumed, invalidating all \texttt{LiveRef} borrows for that lifetime ---
802+
composing Level~10 linearity with Level~9 lifetime safety.
787803

788804
\subsection{Proof Erasure}
789805

docs/whitepapers/academic/typed-wasm.tex

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
The Open University, Milton Keynes, UK\\
7777
\texttt{j.d.a.jewell@open.ac.uk}
7878
}
79-
\date{March 2026 --- Draft}
79+
\date{April 2026 --- Draft}
8080

8181
\begin{document}
8282

@@ -614,24 +614,32 @@ \subsection{Idris 2 and Dependent Types}
614614
``index~$i$ is within the bounds of array of size~$n$'' is a proposition
615615
over the value of~$i$.
616616

617-
A region schema is a value-level record:
617+
A region schema is a flat list of named, typed fields:
618618

619619
\begin{lstlisting}[language=Idris]
620-
data Schema : List (String, FieldType) -> Type where
621-
Nil : Schema []
622-
(::) : Field name ty -> Schema rest -> Schema ((name, ty) :: rest)
620+
-- Schema is a list of named fields; order determines memory layout.
621+
Schema : Type
622+
Schema = List Field
623+
624+
data Field : Type where
625+
MkField : (name : String) -> (ty : WasmType) -> Field
623626
\end{lstlisting}
624627

625-
A typed access is indexed by the schema:
628+
A compile-time field-lookup proof witnesses that a given field exists
629+
in a schema (Level~2 region-binding safety):
626630

627631
\begin{lstlisting}[language=Idris]
628-
data TypedGet : Schema fields -> (name : String) -> FieldType -> Type where
629-
GetHere : TypedGet (MkField {name} {ty} :: rest) name ty
630-
GetThere : TypedGet rest name ty -> TypedGet (f :: rest) name ty
632+
data FieldIn : String -> Schema -> Type where
633+
FieldHere : {auto prf : fieldName f = name}
634+
-> FieldIn name (f :: rest)
635+
FieldThere : FieldIn name rest -> FieldIn name (f :: rest)
631636
\end{lstlisting}
632637

633638
The result type of \lstinline{region.get \$r .name} is \emph{computed}
634-
from the schema, not declared by the programmer.
639+
from the schema via \lstinline{FieldIn} --- not declared by the programmer.
640+
Constructing a \lstinline{FieldHere} or \lstinline{FieldThere} proof is
641+
how the type checker verifies that the named field actually exists;
642+
without it, the access is rejected at compile time.
635643

636644
\subsection{Quantitative Type Theory}
637645
\label{sec:qtt}
@@ -654,15 +662,28 @@ \subsection{Quantitative Type Theory}
654662
\end{tabularx}
655663
\end{table}
656664

657-
Level~10 is implemented by binding allocation handles with quantity~1:
665+
Level~10 is implemented by binding allocation handles with quantity~1.
666+
The allocation protocol produces a linear handle plus a liveness witness;
667+
freeing consumes both:
658668

659669
\begin{lstlisting}[language=Idris]
670+
-- Allocation returns a linear handle (must free exactly once)
671+
-- and a liveness witness (for Level 9 lifetime tracking).
672+
data AllocResult : (token : Nat) -> Type where
673+
MkAllocResult : LinHandle token -> RegionLive token -> AllocResult token
674+
675+
-- Free consumes the handle (quantity 1 = exactly once).
676+
-- The (1 _) annotation rejects zero uses (leak) or two uses (double-free).
660677
freeRegion : (1 _ : LinHandle token) -> RegionLive token -> FreeResult
661678
\end{lstlisting}
662679

663680
The \lstinline{(1 _)} annotation means the type checker rejects any
664681
program where the handle is used zero times (leak) or more than once
665-
(double-free).
682+
(double-free). After \lstinline{freeRegion} returns, both the
683+
\lstinline{LinHandle} and \lstinline{RegionLive} for that token are
684+
consumed, so all \lstinline{LiveRef} borrows with that token's lifetime
685+
become dead --- composing Level~10 linearity with Level~9 lifetime
686+
safety.
666687

667688
\subsection{Proof Erasure}
668689
\label{sec:erasure}

src/abi/TypedWasm/ABI/Linear.idr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,16 @@ allocRegion sid off tok = MkAllocResult (MkLinHandle off sid) (MkRegionLive)
9393

9494
||| Free a region instance. Consumes the linear handle AND the
9595
||| liveness witness. After this call:
96-
||| - The LinHandle is consumed (no double-free possible)
96+
||| - The LinHandle is consumed (no double-free possible — quantity 1)
9797
||| - The RegionLive is consumed (no new borrows possible)
9898
||| - All LiveRefs with lifetime (RegionLife token) become dead
9999
|||
100100
||| This is the dual of allocRegion: alloc produces, free consumes.
101+
||| The (1 _) quantity annotation enforces at the type level that the
102+
||| handle is used exactly once: zero uses = leak (rejected), two uses =
103+
||| double-free (rejected).
101104
public export
102-
freeRegion : LinHandle token -> RegionLive token -> FreeResult
105+
freeRegion : (1 _ : LinHandle token) -> RegionLive token -> FreeResult
103106
freeRegion (MkLinHandle off _) _ = MkFreeResult off
104107

105108
-- ============================================================================

0 commit comments

Comments
 (0)