language

The Unsafe Gate

Direct memory access is fenced behind the unsafe keyword, keeping the risky surface of a codebase small and easy to audit.

Raw-memory operations — load/store, changetype, memory.copy/fill/repeat, and the v128 load/store family — are gated: using one outside an unsafe-marked function is a compile error naming the operation.

unsafe.as
export unsafe function peek(p: usize): i32 {
    return load<i32>(p);      // fine here
}

export function bad(p: usize): i32 {
    return load<i32>(p);      // error: load is unsafe; mark the
}                              // enclosing function 'unsafe'

The keyword is a review marker, not a semantic change — the generated code is identical. It makes the raw-memory surface of a codebase easy to find with a text search. The standard library is exempt, since it exists to wrap these operations.

Addresses below 1024 are reserved: nothing rasc places lives there. An optimized build folds an address’s added constant into the access, so a load or store whose address wraps below 1024 may trap once optimized. load<i32>(p + 16) with p at -8 reads address 8 in a debug build and traps in an optimized one.

A raw pointer into an object is good for one call only. Objects may move between calls, so take the pointer where you use it and never keep it in a field.