| name | rust-expert |
| description | Deep Rust expertise for systems programming with ownership, borrowing, and lifetimes. Use when writing Rust code, understanding ownership errors, implementing traits, working with async/await, or optimizing performance-critical code. Use when this capability is needed. |
| metadata | {"author":"bendourthe"} |
Rust Expert
Specialized expertise in Rust programming, providing deep guidance on ownership and borrowing, lifetime annotations, error handling patterns, async programming, and idiomatic Rust development.
When to Use This Skill
Use this skill for:
- Understanding ownership and borrowing errors
- Writing idiomatic Rust code
- Implementing traits and generics
- Async/await programming
- FFI and unsafe Rust
- Performance optimization
- Memory safety patterns
Trigger phrases: "rust", "ownership", "borrowing", "lifetime", "borrow checker", "cargo", "trait", "impl"
What This Skill Does
Provides Rust expertise including:
- Ownership System: Ownership, borrowing, and lifetime management
- Type System: Traits, generics, associated types
- Error Handling: Result, Option, and error propagation
- Concurrency: Async/await, threads, channels
- Performance: Zero-cost abstractions, optimization
- Safety: Unsafe Rust guidelines, FFI
Instructions
Step 1: Understand Rust's Ownership Model
Ownership Rules:
- Each value has exactly one owner
- When the owner goes out of scope, the value is dropped
- Values can be moved or borrowed
Ownership Examples:
fn main() {
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s2);
}
fn main() {
let x = 5;
let y = x;
println!("{} {}", x, y);
}
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("{} {}", s1, s2);
}
Step 2: Master Borrowing and References
Borrowing Rules:
- You can have either ONE mutable reference OR any number of immutable references
- References must always be valid (no dangling references)
fn main() {
let s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2);
}
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
r1.push_str(" world");
println!("{}", r1);
}
fn main() {
let mut s = String::from("hello");
let r1 = &s;
println!("{}", r1);
= & s;
r2.();
}
Step 3: Work with Lifetimes
Lifetime Annotations:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 {
3
}
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("Attention please: {}", announcement);
self.part
}
}
Lifetime Elision Rules:
fn foo(x: &str) -> &str
fn first_word(s: &str) -> &str
impl MyStruct {
fn get_name(&self) -> &str { &self.name }
}
Step 4: Implement Error Handling
Result and Option Patterns:
use std::fs::File;
use std::io::{self, Read};
fn read_file_contents(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
#[derive(Debug)]
enum AppError {
IoError(io::Error),
ParseError(String),
NotFound,
}
impl From<io::Error> for AppError {
fn from(error: io::Error) -> Self {
AppError::IoError(error)
}
}
use thiserror::Error;
#[derive(Error, Debug)]
enum AppError {
#[error("IO error: {0}")]
Io(#[from] io::Error),
Parse { message: },
(),
}
(id: ) <User> {
users.().(|u| u.id == id).()
}
(id: ) <, AppError> {
= (id).(AppError::((, id)))?;
(user.name)
}
Step 5: Write Async Rust
Async/Await Patterns:
use tokio;
async fn fetch_data(url: &str) -> Result<String, reqwest::Error> {
let response = reqwest::get(url).await?;
let body = response.text().await?;
Ok(body)
}
#[tokio::main]
async fn main() {
let result = fetch_data("https://api.example.com").await;
match result {
Ok(data) => println!("Data: {}", data),
Err(e) => eprintln!("Error: {}", e),
}
}
async fn fetch_multiple() -> Vec<String> {
let urls = vec![
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3",
];
: <_> = urls.().(|url| (url)).();
= futures::future::(futures).;
results.().(|r| r.()).()
}
() {
tokio::( {
{
tokio::time::(Duration::()).;
().;
}
});
}
Step 6: Implement Traits and Generics
Trait Patterns:
trait Summary {
fn summarize(&self) -> String;
fn summarize_author(&self) -> String {
String::from("(Anonymous)")
}
}
struct Article {
title: String,
author: String,
content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{}, by {}", self.title, self.author)
}
fn summarize_author(&self) -> String {
format!("@{}", self.author)
}
}
fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
<T: Summary + Display>(item: &T) { ... }
<T, U>(t: &T, u: &U)
T: Display + ,
U: + ,
{ ... }
{
;
(& ) <::Item>;
}
{
= ;
(& ) <::Item> {
}
}
Step 7: Write Safe Unsafe Code
Unsafe Rust Guidelines:
fn raw_pointer_example() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("r1: {}", *r1);
*r2 = 10;
println!("r2: {}", *r2);
}
}
fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = values.len();
let ptr = values.as_mut_ptr();
assert!(mid <= len);
unsafe {
(
std::slice::(ptr, mid),
std::slice::(ptr.(mid), len - mid),
)
}
}
{
(input: ) ;
}
() {
{
(, (-));
}
}
Unsafe Best Practices:
| Do | Don't |
|---|
| Minimize unsafe blocks | Put entire functions in unsafe |
| Document safety invariants | Assume caller handles safety |
| Use safe abstractions | Expose raw unsafe APIs |
| Test thoroughly | Skip testing unsafe code |
| Review carefully | Blindly trust unsafe code |
Best Practices
- Embrace ownership - Don't fight the borrow checker
- Clone sparingly - Understand the performance cost
- Use iterators - More idiomatic than indexing
- Prefer &str over String - When you don't need ownership
- Handle all Results - Don't use unwrap() in production
- Use clippy - Catches common mistakes
- Minimize unsafe - Keep it small and documented
- Write tests - Especially for unsafe code
Common Patterns
Pattern 1: Builder Pattern
#[derive(Default)]
struct RequestBuilder {
url: String,
method: String,
headers: Vec<(String, String)>,
body: Option<String>,
}
impl RequestBuilder {
fn new() -> Self {
Self::default()
}
fn url(mut self, url: impl Into<String>) -> Self {
self.url = url.into();
self
}
fn method(mut self, method: impl Into<String>) -> Self {
self.method = method.into();
self
}
fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> {
.headers.((key.(), value.()));
}
( , body: <>) {
.body = (body.());
}
() Request {
Request {
url: .url,
method: .method,
headers: .headers,
body: .body,
}
}
}
= RequestBuilder::()
.()
.()
.(, )
.()
.();
Pattern 2: Type State Pattern
struct Locked;
struct Unlocked;
struct Door<State> {
_state: std::marker::PhantomData<State>,
}
impl Door<Locked> {
fn unlock(self) -> Door<Unlocked> {
Door { _state: std::marker::PhantomData }
}
}
impl Door<Unlocked> {
fn lock(self) -> Door<Locked> {
Door { _state: std::marker::PhantomData }
}
fn open(&self) {
println!("Door is open");
}
}
let door: Door<Locked> = Door { _state: std::marker::PhantomData };
let door = door.unlock();
door.open();
Common Rationalizations
| Rationalization | Reality |
|---|
"unwrap() is fine, this Option is always Some" | The one input that makes it None (an empty file, a missing env var) panics the thread and aborts the request instead of returning a recoverable Err. |
"This unsafe block is obviously correct" | Undocumented unsafe hides the invariant the caller must uphold; the next maintainer changes a length or pointer and introduces UB the compiler can no longer catch. |
| "Clippy warnings are just style nits" | Clippy lints like clippy::await_holding_lock flag real deadlock and correctness bugs, not formatting; suppressing them ships the bug. |
"I'll handle the error later with let _ =" | Discarding a Result from a write or flush drops the error, so a partial write looks like success and the corruption is found only by the user. |
Verification
Related Skills
- [[performance-testing]] -- benchmarking Rust code
- [[security-review]] -- reviewing unsafe blocks for soundness
- [[cicd-architect]] -- Rust CI/CD pipelines
- [[code-quality]] -- Rust code-standard scoring
Version: 1.0.0
Last Updated: January 2026
Based on: The Rust Book, awesome-claude-code-subagents patterns
Iterative Refinement Strategy
This skill is optimized for an iterative approach:
- Execute: Perform the core steps defined above.
- Review: Critically analyze the output (coverage, quality, completeness).
- Refine: If targets aren't met, repeat the specific implementation steps with improved context.
- Loop: Continue until the definition of done is satisfied.
Source: bendourthe/Nexus-Hub — distributed by TomeVault.