rust-ownership
Skill47 starsChanged 9 months agoMITView on GitHub
Ownership, borrowing, and lifetime expert. Handles compiler errors E0382, E0597, E0506, E0507, E0515, E0716, E0106 and provides systematic solutions for memory safety patterns.
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 8 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
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
- Very specific: line 32
Only need to read → pass by reference &s1
- Distinctive: line 47
Ensure mutable borrow completes before creating new borrows
- Distinctive: line 62
Use named lifetimes to express relationships
- Distinctive: line 63
Prefer returning owned types
- Very specific: line 131
Use meaningful names: 'connection, 'file
- Distinctive: line 135
Check borrow scope ranges
- Distinctive: line 154
When encountering ownership issues, follow these steps:
- Distinctive: line 166
If failed 3 times → escalate to design level
- Distinctive: line 171
When ownership errors persist, trace to design level:
- Distinctive: line 207
When reviewing ownership-related code:
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 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.
Files
Solution Patterns
Pattern 1: Value Moved After Use
let s1 = String::from("hello");
let s2 = s1;
// println!("{}", s1); // Compile error!Root Cause: Ownership transferred from s1 to s2, s1 is no longer valid.
Solutions:
- Need two copies → use
clone() - Only need to read → pass by reference
&s1 s2is temporary → consider redesign
Pattern 2: Borrow Conflict
let mut s = String::from("hello");
let r1 = &s;
let r2 = &mut s; // Conflict!
// println!("{}", r1);Root Cause: Immutable and mutable borrows coexist.
Solutions:
- Ensure mutable borrow completes before creating new borrows
- Restructure code organization
Pattern 3: Lifetime Mismatch
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() { s1 } else { s2 }
}Root Cause: Return value lifetime must be tied to one of the inputs.
Key Solutions:
- Clarify each reference's lifetime
- Use named lifetimes to express relationships
- Prefer returning owned types
Workflow
Step 1: Who Owns the Data?
| Situation | Owner |
| Function parameter | Caller owns |
| Function-local variable | Function owns (destroyed on return) |
| Struct field | Struct instance owns |
Arc<T> | Multiple shared owners |
Step 2: Is Borrowing Appropriate?
| Operation | Borrow Type | Notes |
| Read-only | &T | Multiple can coexist |
| Needs mutation | &mut T | Only one at a time |
| Will original be modified during borrow? | If yes, that's the issue |
Step 3: Can Lifetimes Be Avoided?
Return String instead of &str
↓
Use owned collections instead of slices
↓
Use Arc/Rc for shared ownership
↓
Lifetimes aren't always necessarySmart Pointer Selection
| Scenario | Choice | Reason |
| Heap-allocate single value | Box<T> | Simple and direct |
| Single-threaded shared reference counting | Rc<T> | Lightweight |
| Multi-threaded shared reference counting | Arc<T> | Atomic operations |
| Need runtime borrow checking | RefCell<T> | Single-threaded interior mutability |
| Multi-threaded interior mutability | Mutex<T> or RwLock<T> | Thread-safe |
Common Pitfalls
| Anti-Pattern | Problem | Correct Approach |
.clone() everywhere | Hides ownership issues | Think about actual ownership needs |
'static for everything | Too loose and imprecise | Use actual required lifetimes |
Box::leak() memory leaks | Memory waste | Use proper lifetime management |
| Fighting the borrow checker | Digging your own hole | Understand and work with compiler design |
Practical Guidance
Common Beginner Questions
1. "When should I use references vs ownership?"
- Function parameters: use references (unless consuming)
- Function returns: use references (if caller doesn't need ownership)
- Storage: consider lifetime complexity
2. "How do I add lifetime annotations?"
- Most cases: compiler can infer
- Need explicit: structs, trait impls, methods returning references
- Use meaningful names:
'connection,'file
3. "Why doesn't this borrow work?"
- Mutable borrows make original inaccessible
- Check borrow scope ranges
- Consider code reorganization
Error Code Quick Reference
| Code | Meaning | Don't Say | Ask Instead |
| E0382 | Use of moved value | "clone it" | Who should own this data? |
| E0597 | Lifetime too short | "extend lifetime" | Are scope boundaries correct? |
| E0506 | Borrow not ended before mutation | "end borrow first" | Where should mutation occur? |
| E0507 | Move out of reference | "clone before move" | Why move from reference? |
| E0515 | Return non-owned data | "return owned" | Should caller own the data? |
| E0716 | Temporary value lifetime insufficient | "bind to variable" | Why is this temporary? |
| E0106 | Missing lifetime parameter | "add 'a" | What's the lifetime relationship? |
Thinking Process
When encountering ownership issues, follow these steps:
1. What's this data's role in the domain?
- Entity (unique identity) → owned
- Value object (interchangeable) → clone/copy acceptable
- Temporary computation result → consider refactor
2. Is ownership design intentional or accidental?
- Intentional → work within constraints
- Accidental → consider redesign
3. Fix symptom or redesign?
- If failed 3 times → escalate to design level
Trace Up (Design Analysis)
When ownership errors persist, trace to design level:
E0382 (moved value)
↑ Ask: What design choice led to this ownership pattern?
↑ Check: Is this an entity or value object?
↑ Check: Are there other constraints?
Persistent E0382 → rust-resource: Should use Arc/Rc for sharing?
Persistent E0597 → rust-type-driven: Are scope boundaries correct?
E0506/E0507 → rust-mutability: Should use interior mutability?Trace Down (Implementation)
From design decisions to implementation:
"Data needs immutable sharing"
↓ Multi-threaded: Arc<T>
↓ Single-threaded: Rc<T>
"Data needs exclusive ownership"
↓ Return owned value
"Data is temporary use only"
↓ Use references within scope
"Need to pass data between functions"
↓ Consider lifetimes or return ownedReview Checklist
When reviewing ownership-related code:
- Each value has a clear owner
- Borrows don't outlive the borrowed data
- Mutable and immutable borrows don't overlap
- Lifetime annotations accurately reflect data relationships
- Smart pointer choice matches threading requirements
.clone()is used intentionally, not to avoid compiler errors- Lifetime elision is leveraged where possible
- Complex lifetime scenarios are documented
Verification Commands
# Check compilation
cargo check
# Run tests
cargo test
# Check for common mistakes
cargo clippy -- -W clippy::clone_on_copy -W clippy::unnecessary_clone
# Verify no memory leaks in tests
cargo test --features leak-checkCommon Pitfalls
1. Clone Abuse
Symptom: .clone() everywhere to satisfy compiler
Fix: Understand actual ownership requirements, use references where possible
2. Lifetime Overuse
Symptom: Complex lifetime annotations everywhere
Fix: Return owned types, use smart pointers
3. Fighting Borrow Checker
Symptom: Constantly rewriting to satisfy compiler
Fix: Step back and redesign data flow
Related Skills
- rust-mutability - Interior mutability patterns (Cell, RefCell)
- rust-concurrency - Send/Sync and thread safety
- rust-unsafe - Raw pointers and manual memory management
- rust-lifetime-complex - Advanced lifetime patterns (HRTB, GAT)
- rust-resource - Resource management and RAII patterns
- rust-type-driven - Type-driven design
Localized Reference
- Chinese version: SKILL_ZH.md - 完整中文版本,包含所有内容
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- adxptived/Rust-Skills★ 1same name
- dawidpereira/rust-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository40 other files it gives its agents.
- .codex/AGENTS.mdAGENTS.md
- SKILL.mdSkill
- rust-actorSkill
- rust-anti-patternSkill
- rust-async-patternSkill
- rust-asyncSkill
- rust-authSkill
- rust-cacheSkill
- rust-codingSkill
- rust-concurrencySkill
- rust-constSkill
- rust-coroutineSkill
- rust-databaseSkill
- rust-distributedSkill
- rust-dpdkSkill
- rust-ebpfSkill
- rust-ecosystemSkill
- rust-embeddedSkill
- rust-error-advancedSkill
- rust-errorSkill
- rust-ffiSkill
- rust-gpuSkill
- rust-learnerSkill
- rust-lifetime-complexSkill
- rust-linear-typeSkill
- rust-macroSkill
- rust-middlewareSkill
- rust-mutabilitySkill
- rust-observabilitySkill
- rust-performanceSkill
- rust-pinSkill
- rust-resourceSkill
- rust-skill-indexSkill
- rust-skillSkill
- rust-testingSkill
- rust-type-drivenSkill
- rust-unsafeSkill
- rust-webSkill
- rust-xacmlSkill
- rust-zero-costSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
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.

