agentleFS
dawidpereiradawidpereira/rust-skills/skills/rust-ownership/SKILL.md

rust-ownership

Skill0 starsChanged 8 months agoMITView on GitHub

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.

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

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

    line 17
  2. Distinctive:

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

    line 31
  3. Distinctive:

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

    line 44
  4. Distinctive:

    If exactly one input lifetime, output gets that lifetime

    line 96
  5. Very specific:

    If &self or &mut self is an input, output gets self's lifetime

    line 97
  6. Very specific:

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

    line 105
  7. Distinctive:

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

    line 138

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.