Pointer and Reference Types
Jiang separates ownership, borrow capability, raw-pointer capability, and binding mutability. Resource movement and lifetime rules are covered in Ownership, Borrowing & Lifetimes.
Pointer and Reference Forms
Section titled “Pointer and Reference Forms”T^: an owning pointer.T&: a shared readonly non-owning borrow.T&!: a unique mutable non-owning borrow. It cannot be implicitly copied.T*: a readonly raw pointer for FFI, ABI, and low-level code.T*!: a writable raw pointer.T[]&: a borrowed slice.T[]^: an owning slice.T[:S]&: a borrowed sentinel slice whose sentinel value isS.
Only T^ and T[]^ express language-level ownership. Compiler-owned names behind these forms are
not available to user source; use the surface syntax directly.
Type-level ! is supported only after & or *: T&! and T*!. A ! after a binding name has a
different purpose—it lets that variable, parameter, global, or field be reassigned and does not
change its type.
Creating Borrows and Raw Pointers
Section titled “Creating Borrows and Raw Pointers”Int value = 123;Int& shared = value$.ref();
Int mutable_value! = 123;Int&! unique = mutable_value$.mut_ref();
Int* raw = unsafe { value$.ptr()};
Int*! mutable_raw = unsafe { mutable_value$.mut_ptr()};ref() and ptr() never manufacture write capability. The mutable forms are mut_ref() and
mut_ptr(), and they require a writable source place. Raw-pointer creation, casts, and indexing
remain inside unsafe.
Dereference and Member Access
Section titled “Dereference and Member Access”T^ can auto-dereference when the expected type is T; $.get() requests an explicit pointee read:
Int^ make_value();
Int^ owner = make_value(); // preserve ownership_ inferred = make_value(); // inferred: Int^Int copied = make_value(); // expected Int: auto-dereferenceInt explicit = owner$.get();Member access can pass through an owning pointer:
struct Item { Int value;}
Item^ item = new Item(value: 42);Int value = item.value;References and raw pointers use $.get() for explicit reads. Writing requires a unique mutable
borrow or mutable-pointee raw pointer:
Int value! = 0;Int&! ref = value$.mut_ref();ref$.set(41);
unsafe { Int*! raw = value$.mut_ptr(); raw$.set(42);}Raw Pointer Indexing
Section titled “Raw Pointer Indexing”T* and T*! can point into contiguous memory, but carry neither a length nor a sentinel guarantee.
The old T[*] and T[*:S] types have been removed. Indexing is always unsafe:
unsafe { UInt8* bytes = source$.ptr(); UInt8 first = bytes[0];
UInt8*! output = destination$.mut_ptr(); output[1] = 42;}Use T[]& when the API should carry a runtime length, and T[:S]& when it should carry a sentinel
guarantee.
Void* and Void*! cannot be dereferenced or indexed because they have no element type. Cast to a
concrete raw-pointer type before accessing memory.
Implicit Operation Layer
Section titled “Implicit Operation Layer”$ prevents receiver auto-dereference and enters the implicit operation layer. Operations such as
$.get(), $.set(), $.ref(), $.mut_ref(), $.ptr(), $.mut_ptr(), and $.move() are covered in
Implicit Operation Layer.