Storage and Runtime Model
Storage Model (v0.1)
Storage representation is an implementation detail, but the runtime should follow these rules.
- Semantics stay value-based (no observable pointer identity).
- Layout for sized types is deterministic (
size,align, field offsets). - Nested sized structs are stored inline.
- Built-in indirection type constructor:
*T. *Tis non-nullable and represented as the address of one heap allocation containingTinline.Option[*T]carries nullable box references at the language level and uses option enum layout with pointer niche optimization in backends.- User-defined recursive/non-stack-allocatable types must use explicit
*Tat recursion/indirection points. - v0.1 uses no implicit boxing for user-defined type recursion.
Inline vs Handle-Backed
- Inline storage is used for small/sized copyable values in locals and parameters.
- Built-in aggregates (
String, slices, arrays) manage their own internal storage and do not require*T. - Pointer-backed storage (
*T) is used for explicit user-directed indirection and recursive graph-like user-defined data. - The immediate payload of
*Tmust not itself be a built-in heap-handle type.
Copyable and Linear Storage
- Copyable heap-backed values use eager copies at copy boundaries.
- v0.1 rule: non-stack-allocatable linear user-defined values require explicit
*Tindirection. - Linear values are move-only, but borrow safety still applies.
Iteration and Move-Out
- Iteration does not move elements out directly.
- Consuming traversal is expressed by moving the container binding (
for (<-collection) |x|).
Runtime Representation
Value Categories
- Immediate: inline scalar (
i64,Bool, small enums). - Heap object: pointer to cell with metadata header.
Heap Header (minimum)
- Type tag/layout id.
- Flags.
Current implementation status:
- Generated Rust pointer copies clone pointee values into fresh cells.
- Generated WASM pointer copies allocate fresh cells, and release frees pointer cells on drop.
- Pointer release also recursively walks heap-backed pointee payloads before freeing the outer pointer cell.
- Generated WASM runtime strings are stored in linear memory; literals stay static and owned string values are freed on drop.
- Generated WASM array storage frees backing allocations on drop.
- Array release walks nested pointer/string/array elements before freeing the outer storage.
- Nested tuple/struct aggregate fields are recursively walked during release, then aggregate storage is freed.
Interpreter/VM Requirements
Minimum conceptual bytecode operations:
ASSIGN_COPY dst, srcASSIGN_MOVE dst, srcBORROW_RO dst, srcBORROW_MUT dst, srcDROP x- field/index mutation ops
The VM must emit precise drops at all scope/control-flow exits.
Runtime IR Boundary (v0.1 direction)
- Runtime execution must not rely on source-level
TypeExprannotations. - Type/mode validation is performed in a checker pass before runtime IR generation.
- Checker failures are hard errors and must stop execution.
- Runtime IR carries only execution data (locals, blocks, ops, control-flow edges), plus dynamic runtime values.
- Runtime checks remain for dynamic semantics (use-after-move, borrow exclusivity/lifetime, Bool condition enforcement).
Runtime IR Shape (Wasm-like, custom)
- Use block + terminator CFG shape similar to Wasm control flow.
- Keep ownership effects explicit as IR ops (
Copy,Move,BorrowRo,BorrowMut,Drop). - Prefer dense entity IDs (
cranelift_entity) and contiguous storage to minimize pointer chasing. - Resolve call targets to function IDs during lowering (avoid runtime name lookup in hot paths).