Ownership and views
Owned values, shared and mutable borrows, and the rules that keep them consistent.
Zmeu has a single ownership model. Each value has exactly one owner; non-owning access is through views.
Owned vs borrowed
Section titled “Owned vs borrowed”let s: String = String.from_str("hello") # ownedlet r: view str = s.as_str() # borrowed (shared)let m: mut view ByteBuf = view_or_buf # borrowed (mutable)- An owned value is dropped when its scope ends.
- A
view Tis a shared, non-owning, non-mutating borrow. - A
mut view Tis a mutable, non-owning borrow: the underlying owner remains in place.
Legacy compatibility syntax &T and &mut T still parses, but new code should prefer view T and mut view T.
Move-out rules
Section titled “Move-out rules”Owned values may be moved out of a local into another owned slot. Once moved, the source slot can’t be used. The compiler tracks this through CFG MIR before any code is lowered.
Owned-storage move-out from self is permitted in consuming builder methods when the surrounding struct does not define drop: see Methods and impl.
Borrow rules
Section titled “Borrow rules”While a view T of some storage is live, the underlying owner cannot be moved or replaced. Structural mutations (e.g. List[T].push) on owned containers are rejected while any borrowed view of the same storage is alive.
This is enforced before lowering: the IR you eventually run never sees a program that violates these rules.
Why a separate view keyword
Section titled “Why a separate view keyword”The view T / mut view T spelling makes the borrow explicit at type sites and at expression sites:
def stream_read(stream: view TcpStream, buf: mut view [u8]) -> Result[usize, NetError]: # ...let bytes: view [u8] = buf.as_slice()The keyword reads more clearly than & when types nest (e.g. view List[Result[T, E]] vs &List[Result[T, E]]) and removes ambiguity at expression position.