03
Ownership 101
Before we can write push and pop we have to talk about three kinds of self. This is the part of Rust where it stops looking like C++. References here are not T* — they're a checked relationship between a borrower and a value that the compiler tracks.
-
self(no ref) consumes the receiver — like a value parameter that takes ownership. After the call, the caller no longer has the value. Use this for methods that intentionally destroy or transform the receiver.impl List { fn destroy(self) { /* self is owned, dropped at end */ } } let list = List::new(); list.destroy(); // list.destroy(); // error: value used after move -
&mut selfis an exclusive borrow — for the duration of the call, no other reference to the value exists. This is the strict mutable-reference form. It's what you use forpush,pop,clear, anything that mutates.impl List { fn clear(&mut self) { self.head = Link::Empty; } } let mut list = List::new(); list.clear(); // ok list.clear(); // ok again — borrow ended at semicolon -
&selfis a shared borrow — read-only, can coexist with other shared borrows but not with&mut. Use this for accessors and queries.impl List { fn is_empty(&self) -> bool { matches!(self.head, Link::Empty) } }