Ownership, Borrowing, and Types
Type-Level Ownership Modes
T: read-only view parameter (default for function parameters).&T: mutable borrow parameter.@T: owned parameter.
Context and Surface Forms
- In type positions (parameter/return annotations, type terms),
Name[...]is a type application/constructor form (for examplePair[i64]). - Pointer indirection is written as
*Tand is non-nullable. - Pointer allocation is written as
@box(expr)and produces*Twhenexpr: T. Option[T]is a built-in optional type constructor. UseOption[*T]for nullable box references.*Trepresents one explicit heap edge to inlineT, so the immediate payloadTcannot itself be another pointer or a built-in heap-handle value.- Built-in sequence type forms:
[T; N]fixed-size array[T]runtime-sized array
- In expression positions,
name(...)is a call expression. - Resolution is context-driven and validated in later semantic passes.
Ownership markers also exist in both spaces:
- Type-level:
T,&T,@T. - Local/value-level:
let x = expr,let @x = expr,&x,<-xforms.
Copyability Classes
- Values are copyable by default.
- Composite types may be explicitly declared
linear(non-copyable). - In MVP, a user-defined
lineartype must contain at least one linear field (directly or transitively through contained types). - Copyable types may not contain linear fields (transitively).
- Linear values can be moved and borrowed, but not copied.
- Copyable containers (
Array, slices,Map) reject linear element values in MVP.
Array literals ([a, b, c]) construct fixed-size arrays by default. When a
[T] type is expected by context, the same literal form constructs an owned
runtime-sized array.
Return annotations do not accept ownership sigils. Return values are always owned.
Local Binding Rules
let x = exprintroduces a read-only view local.let &x = exprintroduces a mutable reference local.let x <- yintroduces a read-only local that now owns the moved value fromy.let @x = exprintroduces an owned local.- Plain
letlocals cannot be assigned through, mutably borrowed, or moved with<-x, even when initialized with<-. - Mutable reference locals (
let &x = expr) may be assigned through and mutably borrowed. - Owned
let @xlocals may be assigned through, mutably borrowed, and explicitly moved.
Read-only parameters and read-only locals are intentionally different:
- A parameter of type
Tmay alias caller storage because it is only a read-only view. - A local created with
let x <- ybecomes the new read-only owner ofy's storage after the move.
Borrowing Rules
- Plain
Tparameters and binders are read-only views. They cannot be assigned through and do not move ownership. &Tborrows are exclusive mutable borrows; they cannot coexist with any other mutable access to the same value.- Mutable borrow overlap checks are place-aware for struct fields and conservative for index/slice projections.
@Tparameters receive an owned value. Plainxcopies into@T, while<-xmoves and invalidates the source binding.- Borrowed values are non-owning and may not escape the function or block that created them.
Lifetime and Destruction
- Heap values are reclaimed when reference count reaches zero.
- No tracing collector is used.
- Frees of large object graphs can still cause long delays (for now).
- Generated Rust and WASM implement box mutation with uniqueness checks before mutable borrows.
For compiler implementation details, see Borrow Checking (Internals).