agentsclimarketplace

Rust ownership

Skill dawidpereira/rust-skills/skills/rust-ownership

Curated Rust skill files for Claude Code: ownership, async, errors, types, architecture, DDD, and more

Install
npx -y skills add dawidpereira/rust-skills --skill rust-ownership

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Rust ownership, borrowing, and lifetime patterns. Use this skill whenever working with move semantics, references, smart pointers (Arc, Rc, Box, Cell, RefCell, Mutex, RwLock), interior mutability, or encountering E0382/E0597/E0506/E0507/E0515/E0716/E0106 errors. Also use when deciding between clone, borrow, or shared ownership, or when lifetime annotations are confusing.

SKILL.md

5.6 KB, as published. Nobody here has run it

Ownership & Lifetimes

Core Question

Who should own this data, and for how long?

Before fixing an ownership error, understand the data's role:

  • Is it shared or exclusive?
  • Is it short-lived or long-lived?
  • Is it transformed or just read?

The compiler tells you what broke. Your job is to figure out why the ownership design led here.


Error → Design Question

Don't just silence the compiler — ask what the error reveals about your design.

ErrorDon't Just SayAsk Instead
E0382 (moved value)"Clone it"Who should own this data?
E0597 (dangling ref)"Extend lifetime"Is the scope boundary correct?
E0506 (assign while borrowed)"End borrow first"Should mutation happen elsewhere?
E0507 (move from reference)"Clone before move"Why are we moving from a reference?
E0515 (return local ref)"Return owned"Should the caller own the data?
E0716 (temporary dropped)"Bind to variable"Why is this a temporary?
E0106 (missing lifetime)"Add 'a"What is the actual lifetime relationship?

If you've tried the same fix twice and it cascades, the ownership design is wrong — not just the syntax.


Quick Decisions

SituationReach ForWhy
Caller doesn't need data afterwardMoveZero cost, transfers ownership
Read-only access&TZero cost borrow
Need to modify borrowed data&mut TExclusive borrow, zero cost
Actually need a separate copy.clone()Heap allocation — make it explicit
Small trivial type (≤16 bytes)CopyImplicit, free duplication
Might need to modify borrowed dataCow<'a, T>Allocates only if mutated
Shared ownership, single threadRc<T>Reference counted, no atomics
Shared ownership, multi threadArc<T>Atomic reference counted
Need mutation through &self (single thread)RefCell<T>Runtime borrow checking
Need mutation through &self (multi thread)Mutex<T> / RwLock<T>Locking, thread-safe
Large type passed by valueBox<T>Move costs 8 bytes instead of N

Smart Pointer Decision Tree

Need shared ownership?
├── Yes → Across threads?
│   ├── Yes → Arc<T>
│   │   └── Need mutation? → Arc<Mutex<T>> or Arc<RwLock<T>>
│   └── No → Rc<T>
│       └── Need mutation? → Rc<RefCell<T>>
└── No → Need heap allocation?
    ├── Yes → Box<T>
    └── No → Use stack (move or borrow)

When choosing between Mutex and RwLock:

  • Reads dominate (>80% reads) → RwLock<T>
  • Frequent writes or very brief locks → Mutex<T>
  • Single thread → RefCell<T> (no locking overhead)
  • Performance critical → consider parking_lot crate

Lifetime Elision

Rust elides lifetimes automatically in most cases. Don't annotate unless required.

The three elision rules:

  1. Each input reference gets its own lifetime
  2. If exactly one input lifetime, output gets that lifetime
  3. If &self or &mut self is an input, output gets self's lifetime

When you MUST annotate:

  • Multiple input references with ambiguous output lifetime
  • Structs holding references
  • Multiple distinct lifetime relationships
  • 'static bounds

Use anonymous lifetime '_ for clarity when the compiler needs a hint but the specific lifetime doesn't matter: impl fmt::Display for Wrapper<'_>.


Usage Scenarios

Scenario 1: "I'm getting E0382 — value used after being moved" → Don't immediately add .clone(). Ask: does the second use actually need ownership? If it only reads, take a reference. If both uses need ownership, consider Rc/Arc or restructuring so one use happens before the other.

Scenario 2: "Should I use Arc or clone this config into each thread?" → If the config is read-only after creation, Arc<Config> is cheaper — one allocation shared by all threads. If each thread might modify its copy, clone before spawning.

Scenario 3: "I need to update a cache behind a shared reference" → This is interior mutability. Single thread? RefCell<HashMap<K, V>>. Multi-thread? Mutex<HashMap<K, V>> or RwLock<HashMap<K, V>> if reads dominate. Consider dashmap for concurrent maps.


Reference Files

Read these when you need depth beyond the quick reference above.

FileRead When
references/borrowing.mdDeciding between borrow, clone, move, Cow; accepting slices vs owned types; lifetime patterns
references/smart-pointers.mdChoosing between Box, Rc, Arc; understanding reference counting; boxing large enum variants
references/interior-mutability.mdWorking with RefCell, Mutex, RwLock; mutation through shared references; lock safety in async

Cross-References

WhenCheck
Error types and propagationrust-errors → Quick Decisions
Trait bounds causing ownership issuesrust-types → Quick Decisions
Locks held across .awaitrust-async → Quick Decisions
Large enum variants or allocation optimizationrust-perf → Quick Decisions

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.