Skip to content

Move Semantics

Overview

Move semantics transfer ownership of handles between variables. Handles are unique; the move keyword is required for all handle transfers (between variables). The with keyword is used to transfer handles into nested scopes.

Syntax

let x = move y;

with x {
    doSomething(x);
}

with x, y, z {
    doSomething(x, y, z);
}

if (cond) with h {
    doSomething(h);
}

if (cond) with h {
    doSomething(h);
} else {
    // h is also transferred here
    doFallback(h);
}

while (cond) with h {
    doSomething(h);
}

Rules

Move Syntax

The move keyword MUST be applied to a local variable in the current scope. move MUST only be usable on lvalues.

Move Source Invalidation

After moving a handle, the source variable MUST be invalidated. For struct handles, the source MUST be set to null. For slice handles, the source MUST be set to a zero-length empty slice.

Handle Uniqueness

Assignment from a handle MUST use move to explicitly transfer ownership.

Handle Movement from Struct Members

Moving a handle from a struct member MUST require a write capability on the enclosing struct. Attempting to move a handle member through a read capability MUST be a compile-time error. Assigning a handle member to a variable through a read capability (e.g., let h = r.inner) MUST be a compile-time error, as assignment from a handle requires move which is prohibited through read. Moving a handle from a struct member MUST invalidate that member. For struct handle members, the member MUST be set to null. For slice handle members, the member MUST be set to a zero-length empty slice.

Moving Handles from This

Inside a member function body, a handle member MAY be moved via move this.handleMember if this has type write StructType. Moving a handle member via this MUST invalidate that member. Attempting to move a handle member when this has type read StructType MUST be a compile-time error.

Capability Restriction

A handle MUST NOT be moved (via move) or transferred (via with) while a capability derived from that handle is still active. A capability is active from the point at which it is produced (via the read or write operator) until the end of the scope in which it was produced or until the capability variable is invalidated, whichever comes first. The compiler MUST enforce this constraint at compile time.

Reference Nullification

When a handle is transferred into a nested scope (via with), the transferring variable MUST be invalidated in the outer scope. The variable MUST NOT become accessible in the outer scope upon exit of the nested scope, whether by normal exit, return, or break.

Nested Scope Permission

Handles MUST NOT be moved by statements in any nested scope without explicit transfer of the variable to the nested scope via with. This applies to all nested scopes including braced blocks, if bodies, while bodies, and region scopes.

With Statement Body

The with body MUST be a non-empty braced block { ... } or a region scope $ { ... }. A bare statement without braces MUST NOT be allowed.

With Statement Forms

The with statement MUST be permitted as a prefix to an if body or while body. When combined with if, the transferred variable(s) MUST be accessible by the same name in both the if and else branches. Each branch MUST independently manage the transferred variable. The compiler MUST enforce all move and capability constraints within each branch independently. After the if/else statement completes, the transferred variable(s) MUST be invalidated in the outer scope regardless of which branch was taken.

With and Null Tracking

When a handle is transferred into a nested scope via with, any compile-time non-null tracking established for that handle MUST be preserved in the nested scope. If the handle is known to be non-null at the point of transfer, the compiler MUST treat it as known-non-null within the nested scope without requiring a redundant null check.

Handle Restriction

The with statement MUST only accept handle types (&T or []T). Primitive types and function pointer types MUST NOT be permitted in a with statement. Variables listed in a with statement MUST belong to the current scope. The with statement MUST NOT be used to transfer a handle from an inner scope (such as a nested region) to an outer scope.

With Entry Conditions

Variables listed in a with statement MUST be valid (not yet moved) in the outer scope at the point of the with. A variable declared within a nested scope MUST NOT be listed in a with statement belonging to an outer scope. Handles MUST be permitted in a with statement regardless of their null state. Multiple variables MAY be listed in a single with statement.

With Exit Conditions

Variables transferred into a nested scope MUST be invalidated in the previously owning scope; the variable MUST NOT become accessible in the outer scope upon exit (whether by return, break, or normal exit) of the nested scope.