gor.bio wiki

Rust Ownership and Borrowing

The compile-time memory model that gives Rust memory safety without garbage collection: every value has one owner, and references borrow under strict rules.

Category: Programming · Created: 2026-08-16 · Updated: 2026-08-16

Illustration: Cargo clippy hello world example
Illustration: Cargo clippy hello world example · Image: Caleb Stanford, CC BY-SA 4.0, via Wikimedia Commons.

Rust guarantees memory safety without a garbage collector by enforcing a set of ownership rules at compile time. Every value in Rust has exactly one owner: the variable that holds it. When the owner goes out of scope, the value is dropped and its memory is freed immediately. There is no shared automatic reclamation and no manual free, which eliminates both use-after-free bugs and the runtime cost of a collector.

Assigning or passing a value transfers ownership rather than copying it, unless the type implements Copy. This is called a move. After a move, the original binding can no longer be used, and the compiler enforces that:

let s = String::from("hello");
let t = s;            // s is moved into t
// println!("{}", s); // compile error: s is no longer valid
println!("{}", t);

Because moves make ownership explicit, every value has exactly one owner at any moment, and double-free or dangling references become compile errors instead of runtime crashes.

Borrowing lets code use a value without taking ownership. An immutable reference &T provides read access; a mutable reference &mut T provides exclusive write access. The borrow checker enforces the central rule: at any time, a value may have either any number of immutable references or exactly one mutable reference, but not both. This rule prevents data races at compile time, since two threads can never hold conflicting access to the same data through references.

References cannot outlive the value they point to. Lifetimes are the compiler's bookkeeping for this constraint: every reference carries an implicit or explicit lifetime, written like &'a T, and the compiler verifies that the reference's lifetime does not exceed the value's. In most functions lifetimes are inferred automatically; explicit annotations are only needed when a function returns a reference tied to one of its inputs.

The result is a system with the performance of manual memory management — no garbage-collection pauses, no reference counting on the hot path — and the safety of a checked language. The same rules that guarantee memory safety also make many concurrency bugs impossible, which is why Rust is widely used for operating systems, embedded software, web servers, and cryptography.

Tags

compilers memory safety rust

Related articles

This text may be freely copied, modified, and reused. See Content Reuse.