Week 7 - Smart Pointers and Interior Mutability¶
7.1 Conceptual Core¶
- A "smart pointer" in Rust is a value that owns a heap allocation and customizes Drop. The std hierarchy:
Box<T>-unique ownership, single heap allocation.Rc<T>-shared ownership, single-threaded, refcount.Arc<T>-shared ownership, atomic refcount, thread-safe.Weak<T>(paired withRc/Arc)-non-owning observer; breaks cycles.- Interior mutability is the controlled violation of "no
&mutwhile&exists." The valid mechanisms: Cell<T>-get/set by value, no references handed out, single-threaded, zero overhead.RefCell<T>-runtime borrow checking, panics on conflict, single-threaded.Mutex<T>/RwLock<T>-runtime borrow checking with thread blocking, multi-threaded.OnceCell<T>/OnceLock<T>-write-once, then immutable.UnsafeCell<T>-the only primitive that legally permits interior mutability; everything above is built atop it.
7.2 Mechanical Detail¶
UnsafeCell<T>is the one type in the language for which&UnsafeCell<T>may be cast to*mut Twithout UB, provided the contents are not aliased mutably. Read the Rustonomicon chapter; it is the keystone.- The memory layout of
Rc<T>: aRcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }allocated as one block. TheRc<T>is aNonNull<RcBox<T>>. Same forArc<T>but withAtomicUsizeand a separate cache line for the refcount on some impls (studytriomphefor the alternative layout). - Reference cycles:
Rc<RefCell<Node>>with two-way edges leaks. The Drop sequencing matters-when refcount reaches zero, the inner value is dropped before the allocation is freed, so cycles inWeakwork. Pinpreview: introduced here only to flag that interior mutability + self-references is the combination that demandsPin. The full treatment is week 11.
7.3 Lab-"Build a Tracing Rc"¶
Implement TracingRc<T> from scratch using UnsafeCell and NonNull. It must:
- Refcount strong and weak references correctly (study std::rc for the algorithm).
- Log every clone/drop to a thread-local trace buffer.
- Pass Miri (cargo +nightly miri test)-meaning your unsafe code is provably free of undefined behavior under the stacked-borrows model.
7.4 Idiomatic & Clippy Drill¶
clippy::rc_buffer,clippy::redundant_allocation,clippy::arc_with_non_send_sync,clippy::mut_from_ref. The last is a soundness lint-understand why it can never be silenced legitimately.
7.5 Production Hardening Slice¶
- Run your
TracingRclab undercargo +nightly miri test. If it fails, fix the unsoundness; do not silence the diagnostic. Addmirito a nightly CI job ascontinue-on-error: false.