← ClaudeAtlas

ownership-not-clonelisted

Use ownership and borrowing instead of reaching for clone, Rc, RefCell, or Arc<Mutex<_>> to silence the borrow checker. Every clone must be explainable. Use when code clones to make an error go away, when a borrow-checker fight is being resolved by copying data, when reviewing Rust dense with .clone() or Rc<RefCell<_>>, or when the user asks whether a clone is necessary.
rewrite-rs/skills · ★ 2 · AI & Automation · score 73
Install: claude install-skill rewrite-rs/skills
# Ownership, Not Clone The borrow checker is a map of where ownership is being fudged, not an obstacle to route around. This skill decides who holds a value and for how long. ## The rule Every `clone` must be explainable in one sentence that is not "the borrow checker complained." A clone that buys a real thing — a value that must outlive the borrow — is fine; one that only silences an error is a deferred design decision. ## Read the error, not the workaround `E0502` (a mutable borrow while an immutable one is still live) and `E0499` (two mutable borrows of the same place) name a lifetime conflict; the fix is in the structure the error describes, not in the `clone` that silences it: ```rust,ignore // No clone: `first` is Copy, so the borrow ends at the let. let first = items[0]; for _ in 0..n { items.push(first); } ``` ## Borrow splitting The borrow checker tracks a whole value through method calls, but fields individually through direct field access. A `&mut self` method that also needs `self.other_field` is the classic false conflict — destructure once: ```rust,ignore // The two fields are separate lets and borrow independently. impl Server { fn handle(&mut self) { let Self { connections, log, .. } = self; for conn in connections.iter_mut() { log.record(conn.id()); } } } ``` `split_at_mut` hands back two disjoint `&mut` halves of one slice; when destructuring is not enough, extract a free function that takes the two