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 &var borrow 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 meets return.
  • Declaring a var without 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 TLesson
needs nothing specialnothing — copies field by fieldCopy
must clean up when a value endsfunc ~T(self: &var T) { … }Destructor
must never exist twicefunc =(self: &var T, other: &T);Non-copyable types
needs real work to duplicatefunc =(self: &var T, other: &T) { … }Custom copy

Lessons

LessonWhat you will learn
11.1Exclusivityone writer at a time: the rule that keeps borrows safe
11.2Copyassignment copies a value, and the copies are independent
11.3Movehand a value over with <- instead of copying it
11.4Destructorrun cleanup when a value goes out of scope with ~T
11.5Non-copyable typesforbid copying a type that owns a resource
11.6Custom copywrite your own copy for a type that needs real work to duplicate
11.7Partial movemove one field out of a struct, and what is cleaned up after
11.8Deferschedule cleanup at the point you start the work, so it cannot be forgotten
11.9Defer returnwhat a deferred action sees when the function returns a value
11.10Initializationa 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.