Skip to content

Q003. What invariants does ownership enforce?

Short Answer

In safe Rust, ownership tracks which places contain initialized values and which path is responsible for cleanup. Moving a non-Copy value makes the source unavailable, non-Copy values are not implicitly duplicated, and only initialized values are used or dropped. Borrowing and lifetimes add reference-validity and aliasing guarantees on top of this.

Deep Dive

The practical ownership invariants are:

  • a place must contain an initialized value before it can be used;
  • moving a non-Copy value transfers it and marks the source as moved from;
  • a moved-out value is not used or dropped through the old place;
  • non-Copy values are not implicitly duplicated;
  • an initialized value follows one valid cleanup path unless destruction is deliberately suppressed or the value is leaked;
  • ownership of a composite value normally includes ownership of its fields.

Reference validity is related but distinct. The borrow checker and lifetime analysis ensure that references do not outlive their referents and enforce Rust's safe aliasing rules.

Internal Model

The compiler performs dataflow analysis over places and control-flow paths. It tracks initialization, moves, and borrows, and rejects a use when the required state cannot be proven.

Drop elaboration then emits cleanup only along paths where a value is initialized. Some control flow requires drop flags, although optimization often removes them.

Example

rust
struct Resource;

impl Drop for Resource {
    fn drop(&mut self) {
        println!("released");
    }
}

fn main() {
    let first = Resource;
    let second = first;

    drop(second);
    // drop(first); // error: first was moved
}

Common Mistakes

  • Reducing the model to the slogan "one value, one owner" without discussing moves and initializedness.
  • Attributing every borrowing and lifetime rule to ownership alone.
  • Saying every value is always dropped; safe Rust permits deliberate leaks.

Follow-ups

  • How does the compiler track initialization through conditional control flow?
  • What are drop flags?
  • How do Rc<T> and Arc<T> represent shared ownership?

References

  • The Rust Programming Language
  • Rust Reference
  • rustc-dev-guide