5 exercises on Rust ownership, borrowing, lifetimes, and smart pointers.
0 / 5 completed
1 / 5
In Rust, what does the borrow checker enforce?
The borrow checker is the part of Rust's compiler that statically enforces the borrowing rules. At any moment a value may have either any number of shared references (&T) or exactly one mutable reference (&mut T), but never both. It also guarantees that no reference outlives the data it points to, preventing dangling pointers. Because these checks happen entirely at compile time, Rust achieves memory safety and data-race freedom with zero runtime overhead and no garbage collector.
2 / 5
What is a lifetime in Rust?
A lifetime is a region of code over which a reference is guaranteed to remain valid. The compiler uses lifetimes to ensure a borrow never outlives the data it points at. Most lifetimes are inferred automatically through lifetime elision, but when relationships are ambiguous you annotate them explicitly with syntax like &'a T and fn foo<'a>(...). Lifetimes carry no runtime cost — they are purely a compile-time tool that lets the borrow checker reason about reference validity across function boundaries and struct fields.
3 / 5
What are Rust's move semantics?
By default Rust uses move semantics: assigning a value or passing it to a function moves ownership, so the original binding becomes invalid and the compiler rejects any later use of it. This guarantees each resource has exactly one owner responsible for freeing it, preventing double-frees. Small types that implement the Copy trait (integers, booleans, simple structs) are instead duplicated bitwise and remain usable. For an explicit deep copy of heap data you call .clone(), which is intentionally visible because it can be expensive.
4 / 5
What is Box<T> in Rust?
Box<T> is the simplest smart pointer: it allocates a value on the heap and owns it, freeing the memory automatically when the box goes out of scope. You reach for it when a type's size is unknown at compile time (recursive types like trees), when you want to move a large value without copying it, or when you need a trait object behind Box<dyn Trait>. Unlike Rc or Arc, a Box has a single owner and adds no reference-counting overhead.
5 / 5
How do Rc and Arc differ in Rust?
Rc<T> (Reference Counted) and Arc<T> (Atomically Reference Counted) both let multiple owners share the same heap value, freeing it when the last clone is dropped. The difference is concurrency: Rc uses non-atomic counters, so it is fast but usable only within a single thread, whereas Arc updates its counts with atomic operations, making it safe to share across threads at a small performance cost. Neither permits mutation directly; you combine them with RefCell or Mutex for interior mutability.