&T is a safe reference to a value of type T.
fn inspect(value: &Record): void {
println(value.name)
}References preserve access to a particular value or interior place without exposing an absolute machine address.
Taking references
Prefix & explicitly takes a reference.
record_ref: &Record = &recordWhen a value is passed where &T is expected, the compiler can insert the
reference take automatically.
inspect(record)The explicit spelling remains useful in an annotation, stored value, or place where intent would otherwise be unclear.
Access
Dereference is implicit for field and method access.
name := record_ref.name
record_ref.validate()There is no ordinary source *reference dereference operator. The compiler
tracks the referenced place and performs the required loads or stores.
Lifetimes
Atoll has no user-written lifetime parameters. Escape analysis determines whether a reference remains frame-local or requires a stable managed target.
fn select(record: &Record): &Field {
return &record.field
}A reference that escapes must keep the correct owning storage alive. Interior references retain enough parent information to reach and pin that owner.
The compiler rejects or promotes a representation when it cannot prove the reference safe across scope exit, escape, or suspension.
Mutation
A reference does not bypass mutability checking.
The binding, parameter, receiver, and referenced place must provide the
required mutable path before a write is legal. mut reference: &T can also
mean the binding holding the reference may be reseated; it does not grant
unrestricted mutation to every T.
Use a method with mut self or an explicitly mutable parameter for APIs that
update through a reference.
Slices
[..]T is a specialized contiguous view built on reference semantics.
fn checksum(data: [..]byte): u64 {
// ...
}A slice includes a range and pins the relevant backing block. It cannot grow, but supported mutation can write through to in-range elements.
Growing the original list can move that owner to new storage while the slice continues to reference its pinned snapshot safely.
See Sequences.
Weak fields
@weak marks a supported optional reference-shaped field as non-owning.
struct Node {
value: int
@weak
parent: Node?
}Weak fields do not keep the referent alive. When the referent is destroyed, the runtime clears registered weak locations.
Restrictions are intentional:
- the field must be nullable;
- the referenced representation must support stable weak registration;
- primitive scalars, strings, tuples, and unsupported inline values cannot be weak targets;
@weaktakes no arguments.
Use weak relationships only when None after referent destruction is valid
domain behavior.
Sharing
An &T reference asks for shared identity, not a deep copy. Equality of
references at the language level still follows the referenced type’s
documented operations; do not use a handle as application identity.
For ordinary read-only parameters, compiler-inferred borrowing is usually
enough. Reserve &T in public signatures for APIs that intentionally expose
a retained reference or interior relationship.
Suspension
Absolute host pointers cannot survive an Atoll suspension because the runtime may resume with a relocated arena base. Safe references use arena-relative, resumable representation when they cross a safepoint.
The MIR verifier rejects a raw pointer live across a suspending terminator.
This distinction is central: safe &T references may be made resumable; raw
machine pointers may not.
Raw pointers
ptr[T] is the unsafe pointer type.
unsafe fn advance(pointer: ptr[byte], offset: usize): ptr[byte] {
return pointer + offset
}Raw pointers are used by intrinsics, host adapters, and low-level prelude
implementation. Pointer arithmetic accepts pointer-sized isize or usize
offsets, and same-pointee subtraction produces isize.
Application code should prefer values, slices, and safe references. Raw pointers have no automatic bounds, lifetime, or suspension guarantee.