Rust's ownership system is its most distinctive feature, enabling memory safety without a garbage collector. These exercises cover ownership, borrowing rules, lifetime annotations, shared ownership patterns, and interior mutability — the concepts every Rust developer must understand.
0 / 5 completed
1 / 5
At standup, a colleague asks what ownership means in Rust. What is the correct answer?
Ownership is Rust's core memory management model. Every value has exactly one owner. When the owner goes out of scope, Rust automatically calls drop() and frees the memory — with no runtime garbage collector. Ownership can be moved (transferring ownership to a new variable, making the old one unusable) or borrowed (temporarily lending the value via a reference). These rules are enforced at compile time by the borrow checker.
2 / 5
During a PR review, a teammate asks what the borrow checker enforces. Which answer is correct?
The borrow checker enforces two core rules at compile time. First, all references must be valid — a reference cannot outlive the data it points to (no dangling pointers). Second, at any point in the code you may have either one mutable reference (&mut T) OR any number of immutable references (&T), but never both at once. These rules eliminate data races and use-after-free bugs without runtime overhead.
3 / 5
In a design review, the team discusses lifetimes in Rust. A junior engineer asks what lifetime annotations like 'a express. What is correct?
Lifetime annotations don't change how long values live — they describe relationships between reference lifetimes so the borrow checker can verify safety. For example, &'a str means 'a reference to a string that lives at least as long as 'a'. When a function returns a reference, the compiler needs to know which input reference's lifetime it derives from. The compiler elides lifetimes in many cases (lifetime elision rules), but explicit annotations are required when the relationship is ambiguous.
4 / 5
An incident report shows a data structure needing multiple owners causing compile errors. A senior engineer asks when to use Rc vs Arc in Rust. What is correct?
Rc<T> (Reference Counted) allows multiple owners of a value in a single thread. Its reference count uses non-atomic operations — fast but notSend, so it cannot cross thread boundaries. Arc<T> (Atomically Reference Counted) uses atomic increment/decrement, making it Send + Sync and safe for multi-threaded shared ownership. Prefer Rc for single-threaded graphs or trees; use Arc when you need to share data across threads.
5 / 5
During a code review, a senior engineer asks what interior mutability means and when RefCell<T> is appropriate. What is accurate?
Interior mutability allows mutating data behind a shared (&T) reference, which the borrow checker normally forbids. RefCell<T> enforces borrow rules at runtime instead of compile time: .borrow() returns an immutable reference (panics if a mutable borrow is active), and .borrow_mut() returns a mutable reference (panics if any borrow is active). Use it in single-threaded code where you genuinely need shared mutability — for example, in a tree where nodes need to mutate each other through shared references. For multi-threaded code, use Mutex<T> instead.