From 042c969e302cb8fb4ac5dd37b4382ec9a49d7a5b Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Fri, 25 Sep 2026 12:55:38 +0700
Subject: [PATCH] Every description of an Allocator value says it is two words
---
docs/BUILT.md | 4 ++--
lib/types.ml | 7 ++++---
web/index.html | 2 +-
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/docs/BUILT.md b/docs/BUILT.md
index 0be3459c..0c3c3e97 100644
--- a/docs/BUILT.md
+++ b/docs/BUILT.md
@@ -4692,8 +4692,8 @@ neither of them a function-value question:
1. The runtime calls `a->proc(a, mode, p, old_size, size, align)` — six C arguments and no transfer channel — and
every Flan function value's signature ends with one. It is the same mismatch a foreign function's address is
refused for, pointing the other way.
-2. `Allocator` is opaque and pointer-width, so there is nowhere for a program to put the `flan_allocator` that
- pointer would have to point at.
+2. `Allocator` is opaque — a pointer to a runtime `flan_allocator` and an incarnation — so there is nowhere for a
+ program to put the `flan_allocator` that pointer would have to point at.
The refusal message says both, and `programs/user-allocator.flan` is the row that holds it. `(arena-new ...)` over a
backing buffer remains the parameterised allocator that does exist.
diff --git a/lib/types.ml b/lib/types.ml
index 42a309bd..4ff45ee0 100644
--- a/lib/types.ml
+++ b/lib/types.ml
@@ -38,9 +38,10 @@ type t =
is what lets spec-memory.md's "procedure plus an opaque data pointer" be
expressed with none of milestone 5's function values — the procedure is a
C symbol the emitter names and no Flan type ever mentions it. At run time
- it is a pointer to the runtime's [flan_allocator], never a copy of one:
- the capability set and the epoch have to be shared by every container
- made from it, and a copy would give each its own. *)
+ it is two words: a pointer to the runtime's [flan_allocator], never a
+ copy of one — the capability set and the epoch have to be shared by every
+ container made from it — and the incarnation of it the value was made
+ for, which arena-destroy bumps so a stale value traps on use. *)
| Alloc
(* [(Vec T)]: ptr + len + cap + allocator, owning and move-only. One
type-erased runtime over (size, align) stands behind every instantiation,
diff --git a/web/index.html b/web/index.html
index bee16947..f424d0ce 100644
--- a/web/index.html
+++ b/web/index.html
@@ -528,7 +528,7 @@ notation reads as exactly one data item.
(Fn [T ...] R) | a function value, which may have captured | a code address and an environment pointer |
(CFn [T ...] R) | a function value that cannot capture — the C is what a C function pointer would need, not a way to reach C today | a pointer |
dyn | a value the runtime knows the type of and the checker does not — see dyn | one word, on a collected heap |
-Allocator | an opaque builtin: a proc, its data and a capability set | a pointer to that |
+Allocator | an opaque builtin: a proc, its data and a capability set | a pointer to that, and a count that says whether it has since been destroyed |
$t | a type variable — see generics | whatever it is instantiated at |
| a struct | value type | fields in declaration order |
| a tagged data type | defdata, matched by case | tag + the widest payload |