From claude-initial-setup
Master Rust's ownership, borrowing, and lifetime system for memory-safe code. Use when the user encounters borrow checker errors, lifetime annotations, needs smart pointers (Box/Rc/Arc), works with move semantics, or asks about Clone vs Copy, ownership transfer, and reference management in Rust.
npx claudepluginhub versoxbt/claude-initial-setup --plugin claude-initial-setupThis skill uses the workspace's default tool permissions.
Understand and apply Rust's ownership system to write memory-safe code without
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Understand and apply Rust's ownership system to write memory-safe code without a garbage collector. Master borrowing rules, lifetimes, and smart pointers.
Three rules govern all Rust memory:
fn main() {
let name = String::from("Alice"); // name owns the String
let greeting = greet(name); // ownership moves to greet
// println!("{name}"); // ERROR: name was moved
println!("{greeting}");
}
fn greet(name: String) -> String { // takes ownership
format!("Hello, {name}!") // returns a new owned String
}
Borrow data without taking ownership. Two rules:
&T) OR exactly one mutable reference (&mut T).fn analyze(data: &[i32]) -> (i32, i32) {
// Shared borrow: can read, cannot modify
let sum: i32 = data.iter().sum();
let count = data.len() as i32;
(sum, count)
}
fn normalize(data: &mut Vec<f64>) {
// Mutable borrow: can read and modify
let max = data.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
if max != 0.0 {
for val in data.iter_mut() {
*val /= max;
}
}
}
fn main() {
let mut values = vec![1.0, 2.0, 3.0];
normalize(&mut values); // mutable borrow
let (sum, _) = analyze(&[1, 2, 3]); // shared borrow
println!("{sum}");
}
Lifetimes tell the compiler how long references are valid. Most are inferred; annotate when the compiler cannot determine the relationship.
// The returned reference lives as long as the shortest input lifetime
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() >= b.len() { a } else { b }
}
// Lifetime in structs: the struct cannot outlive the referenced data
struct Excerpt<'a> {
text: &'a str,
}
impl<'a> Excerpt<'a> {
fn first_word(&self) -> &'a str {
self.text.split_whitespace().next().unwrap_or("")
}
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let excerpt = Excerpt {
text: novel.split('.').next().unwrap(),
};
println!("{}", excerpt.first_word());
}
Use smart pointers when ownership rules need more flexibility.
// Box<T>: heap allocation, single owner
fn build_tree() -> Box<Node> {
Box::new(Node {
value: 1,
left: Some(Box::new(Node { value: 2, left: None, right: None })),
right: Some(Box::new(Node { value: 3, left: None, right: None })),
})
}
// Rc<T>: shared ownership, single-threaded (reference counted)
use std::rc::Rc;
fn shared_config() {
let config = Rc::new(AppConfig::default());
let service_a = Service::new(Rc::clone(&config));
let service_b = Service::new(Rc::clone(&config));
// Both services share the same config; dropped when last Rc is dropped
}
// Arc<T>: shared ownership, thread-safe (atomic reference counted)
use std::sync::Arc;
fn concurrent_cache() {
let cache = Arc::new(Mutex::new(HashMap::new()));
let handles: Vec<_> = (0..4)
.map(|i| {
let cache = Arc::clone(&cache);
std::thread::spawn(move || {
cache.lock().unwrap().insert(i, i * 10);
})
})
.collect();
for h in handles {
h.join().unwrap();
}
}
Copy: bitwise copy, implicit, for small stack types (integers, bools, tuples of Copy types).
Clone: explicit .clone(), for types that need deep duplication.
// Copy: automatically duplicated on assignment
let x: i32 = 42;
let y = x; // x is copied, both x and y are valid
println!("{x} {y}");
// Clone: explicit duplication
let a = String::from("hello");
let b = a.clone(); // deep copy -- both a and b are valid
println!("{a} {b}");
// Without clone, a would be moved:
let c = String::from("world");
let d = c; // c is MOVED to d
// println!("{c}"); // ERROR: c was moved
// Derive both when your struct contains only Copy types
#[derive(Debug, Clone, Copy)]
struct Point {
x: f64,
y: f64,
}
Solutions to frequent borrow checker issues.
// Problem: cannot borrow as mutable because also borrowed as immutable
// Solution: limit the scope of the immutable borrow
fn update_map(map: &mut HashMap<String, Vec<i32>>, key: &str) {
// Use entry API to avoid double-borrow
map.entry(key.to_string())
.or_insert_with(Vec::new)
.push(42);
}
// Problem: returning a reference to a local variable
// Solution: return owned data
fn create_greeting(name: &str) -> String {
// Return owned String, not &str
format!("Hello, {name}!")
}
// Problem: self-referential struct
// Solution: use indices instead of references, or use Pin
struct Document {
content: String,
// Instead of &str references into content, store byte offsets
highlights: Vec<(usize, usize)>,
}
impl Document {
fn highlighted_text(&self, idx: usize) -> &str {
let (start, end) = self.highlights[idx];
&self.content[start..end]
}
}
Cloning to silence the borrow checker -- .clone() everywhere is a sign of
misunderstood ownership. Restructure code to use borrows instead.
Unnecessary Arc<Mutex<T>> -- Only use Arc when data is shared across threads.
Single-threaded code should use Rc or plain ownership.
Lifetime annotations on everything -- Let the compiler infer lifetimes. Only annotate when the compiler asks or when the relationship is ambiguous.
Returning references from functions that create data -- Functions that allocate must return owned types. References can only point to data that outlives them.
| Type | Ownership | Thread-safe | Heap | Use Case |
|---|---|---|---|---|
T | Sole owner | N/A | Stack* | Default |
&T | Shared borrow | Yes (if T: Sync) | No | Read access |
&mut T | Exclusive borrow | No | No | Write access |
Box<T> | Sole owner | N/A | Yes | Large/recursive types |
Rc<T> | Shared | No | Yes | Single-thread sharing |
Arc<T> | Shared | Yes | Yes | Multi-thread sharing |
Move vs Copy: types implementing Copy are duplicated on assignment; all others are moved.