Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transfer or copy ownership

A list has one owner responsible for its mutable contents. Assigning it to another binding transfers that responsibility:

def main() -> Result[(), AllocError | IoError]:
    original = [10, 20]?
    mut changed = original
    changed.append(30)?
    print(changed)?
    Ok(())
[10, 20, 30]

The assignment moves the list. The old binding cannot be used afterward:

def main() -> Result[(), AllocError | IoError]:
    original = [10, 20]?
    changed = original
    print(original)?
    Ok(())
use of moved binding `original`

Passing a collection to an owned parameter or returning it also transfers ownership. A move transfers the existing storage rather than duplicating it.

Use copy(value)? when you need independent contents. Copying observes the source and returns Result[T, AllocError], so the source remains usable whether copying succeeds or fails. Nested mutable contents are copied too; immutable strings may share their existing storage.

Numbers and booleans copy on assignment. Strings remain usable after assignment because their storage is immutable. Tuples containing only these values copy; tuples containing collections move.

A value that copies needs no copy(...)?: write name = original for a string. plenty --check warns about copy(x)? when the type of x already copies. Use copy for values that move, such as lists, when you need two independent owners.

A mutable owner can receive a new value after moving its previous one. The compiler checks all continuing paths: a move on one branch can cause a use of possibly moved binding diagnostic later.