Part 11: Ownership
Every value in a Rux program has exactly one owner — a variable, a parameter, a field — and the owner decides when the value's life ends. Most of the time you never think about it: numbers and small structs are copied freely, and nothing needs cleaning up. This part is about the values where it matters — a hotel key that must be handed back once, a valve that must be closed on every path, a sheet whose copies must each be shredded — and about the rules the compiler checks so that cleanup happens exactly once, never twice and never not at all.
What you will learn
- Why a
&varborrow is exclusive, and why a borrow ends at its last use. - What a copy is, and where one happens: binding, passing, returning and assigning.
- Handing a value on with
<-in a binding, an argument and a return, and what happens to the old name. - Writing a destructor,
func ~T(self: &var T), and when the compiler runs it — newest value first. - Prohibiting copies with a bodyless
func =, or writing your own copy with a body. - Why one field cannot be moved out of a struct, and how a moving pattern takes it apart instead.
- Registering cleanup with
defer, its reverse order, and how it meetsreturn. - Declaring a
varwithout a value, and the compiler's check that every path assigns it.
The life of a value
flowchart LR
b(["Begins<br/>let, var, a constructor<br/>11.10"]) --> h{"Handed on?"}
h -- "= copy<br/>11.2, 11.6" --> two["two values,<br/>each with its own end"]
h -- "<- move<br/>11.3, 11.5, 11.7" --> one["one value,<br/>a new owner"]
h -- "& or &var borrow<br/>11.1" --> same["one value,<br/>the same owner"]
two --> e(["Ends<br/>scope, replacement, return<br/>~T runs: 11.4"])
one --> e
same --> e
w["defer: cleanup for a piece<br/>of work, 11.8, 11.9"] -.-> e| A type that… | Write in extend T | Lesson |
|---|---|---|
| needs nothing special | nothing — copies field by field | Copy |
| must clean up when a value ends | func ~T(self: &var T) { … } | Destructor |
| must never exist twice | func =(self: &var T, other: &T); | Non-copyable types |
| needs real work to duplicate | func =(self: &var T, other: &T) { … } | Custom copy |
Lessons
| Lesson | What you will learn | |
|---|---|---|
| 11.1 | Exclusivity | one writer at a time: the rule that keeps borrows safe |
| 11.2 | Copy | assignment copies a value, and the copies are independent |
| 11.3 | Move | hand a value over with <- instead of copying it |
| 11.4 | Destructor | run cleanup when a value goes out of scope with ~T |
| 11.5 | Non-copyable types | forbid copying a type that owns a resource |
| 11.6 | Custom copy | write your own copy for a type that needs real work to duplicate |
| 11.7 | Partial move | move one field out of a struct, and what is cleaned up after |
| 11.8 | Defer | schedule cleanup at the point you start the work, so it cannot be forgotten |
| 11.9 | Defer return | what a deferred action sees when the function returns a value |
| 11.10 | Initialization | a variable must be assigned before it is read |
Before you start
Finish Parts 1–10 first. This part leans most on Part 6: Types — Reference, Mutable reference, Method and Constructor — and on Destructure and Struct pattern, which Partial move turns into a way of taking values apart. Each lesson's package is in the Examples repository's Ownership/ folder:
cd Examples/Ownership/Exclusivity
rux run
After this part
Part 12: Interfaces describes behaviour that many types share — and lets a type declare its own == and other operators the way this part declared its own =. Ownership comes back in Part 15: Memory, where a Box owns a block of memory and gives it back in its destructor, exactly as the keys and sheets here gave back their rooms and paper. The next checkpoint projects, Circle and Quadratic, come after Part 16.
For related rules, see Mutability of structs, var and Methods in the Rux Reference.