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 a generator’s progress

A generator owns a position in an advancing computation. Assignment transfers that owner instead of copying the position:

def once() -> Generator[i64]:
    yield 42

def main() -> Result[(), AllocError | IoError]:
    first = once()
    second = first
    print(list(second)?)?
    Ok(())
[42]

After a move, the old binding cannot be used:

def once() -> Generator[i64]:
    yield 42

def main() -> Result[(), AllocError | IoError]:
    first = once()
    second = first
    list(first)?
    pass
    Ok(())
use of moved binding `first`

Owned arguments, returns, and for iteration also move generators. next(&mut it) borrows a mutable generator without consuming its owner; next(it) remains a shorthand. A mutable binding can be reinitialized after moving its previous value.

The compiler checks all possible continuing paths. A move on just one branch makes later reuse unsafe, reported as use of possibly moved binding. Within a loop, an outer generator must be reinitialized before any path repeats the loop. Generators cannot be stored in collections or user-defined enum payloads yet.

See Borrow a collection for the borrowing rules.

Drop without resuming

Use drop(value) to release an owner earlier. The consumed binding becomes unavailable; a mutable binding may then receive another value:

def pending() -> Generator[i64]:
    yield 1

def main() -> Result[(), AllocError | IoError]:
    mut numbers = [1, 2, 3]?
    drop(numbers)
    numbers = [4]?
    print(numbers)?

    task = pending()
    drop(task)
    print("done")?
    Ok(())
[4]
done

Dropping a generator cleans its captured values without resuming its body. Borrow checking prevents dropping an owner while a reference still needs it. A borrow can end at its last use; that does not implicitly destroy its owner.